@mclawnet/agent 0.6.20 โ†’ 0.6.22

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.
Files changed (99) hide show
  1. package/cli.js +63 -0
  2. package/dist/__tests__/checkpoint.test.d.ts +2 -0
  3. package/dist/__tests__/checkpoint.test.d.ts.map +1 -0
  4. package/dist/__tests__/fs-handler-decode.test.d.ts +2 -0
  5. package/dist/__tests__/fs-handler-decode.test.d.ts.map +1 -0
  6. package/dist/__tests__/idle-sweeper.test.d.ts +2 -0
  7. package/dist/__tests__/idle-sweeper.test.d.ts.map +1 -0
  8. package/dist/__tests__/mcp-config.test.d.ts +2 -0
  9. package/dist/__tests__/mcp-config.test.d.ts.map +1 -0
  10. package/dist/__tests__/schedule-runtime-spawn.test.d.ts +2 -0
  11. package/dist/__tests__/schedule-runtime-spawn.test.d.ts.map +1 -0
  12. package/dist/__tests__/schedule-runtime.test.d.ts +2 -0
  13. package/dist/__tests__/schedule-runtime.test.d.ts.map +1 -0
  14. package/dist/__tests__/session-limit.test.d.ts +2 -0
  15. package/dist/__tests__/session-limit.test.d.ts.map +1 -0
  16. package/dist/__tests__/swarm-cli-client.test.d.ts +2 -0
  17. package/dist/__tests__/swarm-cli-client.test.d.ts.map +1 -0
  18. package/dist/__tests__/swarm-control-dispatch.test.d.ts +2 -0
  19. package/dist/__tests__/swarm-control-dispatch.test.d.ts.map +1 -0
  20. package/dist/__tests__/swarm-session-bridge.test.d.ts +2 -0
  21. package/dist/__tests__/swarm-session-bridge.test.d.ts.map +1 -0
  22. package/dist/backend-adapter.d.ts +43 -0
  23. package/dist/backend-adapter.d.ts.map +1 -1
  24. package/dist/checkpoint.d.ts +67 -0
  25. package/dist/checkpoint.d.ts.map +1 -0
  26. package/dist/{chunk-RIK7IXSW.js โ†’ chunk-WJWCYGLQ.js} +1130 -147
  27. package/dist/chunk-WJWCYGLQ.js.map +1 -0
  28. package/dist/errors.d.ts +40 -0
  29. package/dist/errors.d.ts.map +1 -0
  30. package/dist/fs-handler.d.ts.map +1 -1
  31. package/dist/hub-connection.d.ts +13 -0
  32. package/dist/hub-connection.d.ts.map +1 -1
  33. package/dist/index.js +1 -1
  34. package/dist/schedule-runtime.d.ts +125 -0
  35. package/dist/schedule-runtime.d.ts.map +1 -0
  36. package/dist/session-manager.d.ts +102 -0
  37. package/dist/session-manager.d.ts.map +1 -1
  38. package/dist/skill-loader.d.ts +20 -0
  39. package/dist/skill-loader.d.ts.map +1 -1
  40. package/dist/start.d.ts +2 -0
  41. package/dist/start.d.ts.map +1 -1
  42. package/dist/start.js +1 -1
  43. package/dist/swarm-cli-client.d.ts +24 -0
  44. package/dist/swarm-cli-client.d.ts.map +1 -0
  45. package/dist/swarm-cli-client.js +83 -0
  46. package/dist/swarm-cli-client.js.map +1 -0
  47. package/dist/swarm-control-dispatch.d.ts +47 -0
  48. package/dist/swarm-control-dispatch.d.ts.map +1 -0
  49. package/dist/swarm-session-bridge.d.ts +22 -0
  50. package/dist/swarm-session-bridge.d.ts.map +1 -0
  51. package/package.json +6 -4
  52. package/skills/cocos-creator-3x-cn/SKILL.md +475 -0
  53. package/skills/cocos-creator-3x-cn/references/framework/asset-management.md +322 -0
  54. package/skills/cocos-creator-3x-cn/references/framework/component-system.md +348 -0
  55. package/skills/cocos-creator-3x-cn/references/framework/event-patterns.md +410 -0
  56. package/skills/cocos-creator-3x-cn/references/framework/playable-optimization.md +257 -0
  57. package/skills/cocos-creator-3x-cn/references/language/performance.md +363 -0
  58. package/skills/cocos-creator-3x-cn/references/language/quality-hygiene.md +307 -0
  59. package/skills/cocos-creator-3x-cn/references/review/architecture-review.md +183 -0
  60. package/skills/cocos-creator-3x-cn/references/review/quality-review.md +251 -0
  61. package/skills/cocos-performance-optimizer/SKILL.md +214 -0
  62. package/skills/game-development/2d-games/SKILL.md +129 -0
  63. package/skills/game-development/3d-games/SKILL.md +145 -0
  64. package/skills/game-development/SKILL.md +175 -0
  65. package/skills/game-development/game-art/SKILL.md +195 -0
  66. package/skills/game-development/game-audio/SKILL.md +200 -0
  67. package/skills/game-development/game-design/SKILL.md +139 -0
  68. package/skills/game-development/mobile-games/SKILL.md +118 -0
  69. package/skills/game-development/multiplayer/SKILL.md +142 -0
  70. package/skills/game-development/pc-games/SKILL.md +154 -0
  71. package/skills/game-development/vr-ar/SKILL.md +133 -0
  72. package/skills/game-development/web-games/SKILL.md +160 -0
  73. package/skills/game-engine/SKILL.md +140 -0
  74. package/skills/game-engine/assets/2d-maze-game.md +528 -0
  75. package/skills/game-engine/assets/2d-platform-game.md +1855 -0
  76. package/skills/game-engine/assets/gameBase-template-repo.md +310 -0
  77. package/skills/game-engine/assets/paddle-game-template.md +1528 -0
  78. package/skills/game-engine/assets/simple-2d-engine.md +507 -0
  79. package/skills/game-engine/references/3d-web-games.md +754 -0
  80. package/skills/game-engine/references/algorithms.md +843 -0
  81. package/skills/game-engine/references/basics.md +343 -0
  82. package/skills/game-engine/references/game-control-mechanisms.md +617 -0
  83. package/skills/game-engine/references/game-engine-core-principles.md +695 -0
  84. package/skills/game-engine/references/game-publishing.md +352 -0
  85. package/skills/game-engine/references/techniques.md +894 -0
  86. package/skills/game-engine/references/terminology.md +354 -0
  87. package/skills/game-engine/references/web-apis.md +1394 -0
  88. package/skills/theone-cocos-standards/SKILL.md +557 -0
  89. package/skills/theone-cocos-standards/references/framework/component-system.md +645 -0
  90. package/skills/theone-cocos-standards/references/framework/event-patterns.md +433 -0
  91. package/skills/theone-cocos-standards/references/framework/playable-optimization.md +429 -0
  92. package/skills/theone-cocos-standards/references/framework/size-optimization.md +308 -0
  93. package/skills/theone-cocos-standards/references/language/modern-typescript.md +658 -0
  94. package/skills/theone-cocos-standards/references/language/performance.md +580 -0
  95. package/skills/theone-cocos-standards/references/language/quality-hygiene.md +582 -0
  96. package/skills/theone-cocos-standards/references/review/architecture-review.md +250 -0
  97. package/skills/theone-cocos-standards/references/review/performance-review.md +288 -0
  98. package/skills/theone-cocos-standards/references/review/quality-review.md +239 -0
  99. package/dist/chunk-RIK7IXSW.js.map +0 -1
@@ -0,0 +1,239 @@
1
+ # TypeScript Quality Review
2
+
3
+ This review focuses on TypeScript code quality issues including access modifiers, strict mode compliance, error handling, and code hygiene.
4
+
5
+ ## TypeScript Strict Mode Violations
6
+
7
+ ```typescript
8
+ // โŒ CRITICAL: Strict mode disabled
9
+ // tsconfig.json
10
+ {
11
+ "compilerOptions": {
12
+ "strict": false // Bad!
13
+ }
14
+ }
15
+
16
+ // โœ… CORRECT: Enable strict mode
17
+ {
18
+ "compilerOptions": {
19
+ "strict": true,
20
+ "noImplicitAny": true,
21
+ "strictNullChecks": true,
22
+ "strictFunctionTypes": true,
23
+ "strictBindCallApply": true,
24
+ "strictPropertyInitialization": true
25
+ }
26
+ }
27
+
28
+ // Severity: ๐Ÿ”ด Critical
29
+ // Fix: Enable strict mode in tsconfig.json
30
+ ```
31
+
32
+ ## Access Modifier Violations
33
+
34
+ ```typescript
35
+ // โŒ CRITICAL: Missing access modifiers
36
+ @ccclass('NoModifiers')
37
+ export class NoModifiers extends Component {
38
+ playerNode: Node | null = null; // Implicitly public!
39
+ currentHealth: number = 100; // Implicitly public!
40
+
41
+ updateHealth(value: number) { // Implicitly public!
42
+ this.currentHealth = value;
43
+ }
44
+ }
45
+
46
+ // โœ… CORRECT: Explicit modifiers
47
+ @ccclass('WithModifiers')
48
+ export class WithModifiers extends Component {
49
+ @property(Node)
50
+ private readonly playerNode: Node | null = null;
51
+
52
+ private currentHealth: number = 100;
53
+
54
+ public updateHealth(value: number): void {
55
+ this.currentHealth = value;
56
+ }
57
+ }
58
+
59
+ // Severity: ๐Ÿ”ด Critical
60
+ // Fix: Add access modifiers (public/private/protected) to all members
61
+ ```
62
+
63
+ ## Silent Error Handling
64
+
65
+ ```typescript
66
+ // โŒ CRITICAL: Silent failures
67
+ @ccclass('SilentErrors')
68
+ export class SilentErrors extends Component {
69
+ public getPlayer(id: string): Player | undefined {
70
+ const player = this.players.get(id);
71
+ return player; // Caller doesn't know why it failed
72
+ }
73
+ }
74
+
75
+ // โœ… CORRECT: Throw exceptions
76
+ @ccclass('ThrowExceptions')
77
+ export class ThrowExceptions extends Component {
78
+ public getPlayer(id: string): Player {
79
+ const player = this.players.get(id);
80
+ if (!player) {
81
+ throw new Error(`Player not found: ${id}`);
82
+ }
83
+ return player;
84
+ }
85
+ }
86
+
87
+ // Severity: ๐Ÿ”ด Critical
88
+ // Fix: Throw exceptions for errors, not silent failures
89
+ ```
90
+
91
+ ## console.log in Production
92
+
93
+ ```typescript
94
+ // โŒ CRITICAL: Unconditional console.log
95
+ @ccclass('ConsoleLogBad')
96
+ export class ConsoleLogBad extends Component {
97
+ protected update(dt: number): void {
98
+ console.log('Update'); // In production build!
99
+ }
100
+ }
101
+
102
+ // โœ… CORRECT: Conditional or removed
103
+ @ccclass('ConsoleLogGood')
104
+ export class ConsoleLogGood extends Component {
105
+ protected update(dt: number): void {
106
+ if (CC_DEBUG) {
107
+ console.log('Update');
108
+ }
109
+ }
110
+ }
111
+
112
+ // Severity: ๐Ÿ”ด Critical (for playables)
113
+ // Impact: Bundle size increase, performance
114
+ // Fix: Wrap in CC_DEBUG or remove entirely
115
+ ```
116
+
117
+ ## Inline Comments Instead of Descriptive Names
118
+
119
+ ```typescript
120
+ // โŒ IMPORTANT: Comments explaining unclear code
121
+ @ccclass('InlineCommentsBad')
122
+ export class InlineCommentsBad extends Component {
123
+ private h: number = 100; // health
124
+
125
+ public td(a: number): void { // take damage
126
+ this.h = this.h - a; // subtract
127
+ if (this.h <= 0) { // dead
128
+ this.hd(); // handle death
129
+ }
130
+ }
131
+ }
132
+
133
+ // โœ… CORRECT: Self-explanatory names
134
+ @ccclass('InlineCommentsGood')
135
+ export class InlineCommentsGood extends Component {
136
+ private currentHealth: number = 100;
137
+
138
+ public takeDamage(amount: number): void {
139
+ this.currentHealth -= amount;
140
+ if (this.isDead()) {
141
+ this.handleDeath();
142
+ }
143
+ }
144
+
145
+ private isDead(): boolean {
146
+ return this.currentHealth <= 0;
147
+ }
148
+
149
+ private handleDeath(): void {
150
+ // Implementation
151
+ }
152
+ }
153
+
154
+ // Severity: ๐ŸŸก Important
155
+ // Fix: Use descriptive names, remove inline comments
156
+ ```
157
+
158
+ ## Missing readonly/const
159
+
160
+ ```typescript
161
+ // โŒ IMPORTANT: Mutable when should be immutable
162
+ @ccclass('MissingReadonly')
163
+ export class MissingReadonly extends Component {
164
+ @property(Node)
165
+ private targetNode: Node | null = null; // Should be readonly
166
+
167
+ private maxHealth: number = 100; // Should be static readonly
168
+ }
169
+
170
+ // โœ… CORRECT: Use readonly/const
171
+ @ccclass('WithReadonly')
172
+ export class WithReadonly extends Component {
173
+ @property(Node)
174
+ private readonly targetNode: Node | null = null;
175
+
176
+ private static readonly MAX_HEALTH: number = 100;
177
+ }
178
+
179
+ // Severity: ๐ŸŸก Important
180
+ // Fix: Add readonly to fields not reassigned, use static readonly for constants
181
+ ```
182
+
183
+ ## Using `any` Type
184
+
185
+ ```typescript
186
+ // โŒ IMPORTANT: Using any without justification
187
+ @ccclass('UsingAny')
188
+ export class UsingAny extends Component {
189
+ private data: any = {}; // Type safety lost
190
+
191
+ public processData(input: any): any {
192
+ return input; // No type checking
193
+ }
194
+ }
195
+
196
+ // โœ… CORRECT: Use proper types
197
+ interface PlayerData {
198
+ id: string;
199
+ name: string;
200
+ level: number;
201
+ }
202
+
203
+ @ccclass('WithTypes')
204
+ export class WithTypes extends Component {
205
+ private data: Map<string, PlayerData> = new Map();
206
+
207
+ public processData(input: PlayerData): PlayerData {
208
+ return input;
209
+ }
210
+ }
211
+
212
+ // Severity: ๐ŸŸก Important
213
+ // Fix: Define proper types and interfaces, avoid `any`
214
+ ```
215
+
216
+ ## Summary: Quality Review Checklist
217
+
218
+ **๐Ÿ”ด Critical (Must Fix):**
219
+ - [ ] TypeScript strict mode enabled in tsconfig.json
220
+ - [ ] All members have access modifiers (public/private/protected)
221
+ - [ ] Exceptions thrown for errors (no silent failures)
222
+ - [ ] console.log removed or wrapped in CC_DEBUG
223
+ - [ ] No nullable warnings (proper null handling)
224
+
225
+ **๐ŸŸก Important (Should Fix):**
226
+ - [ ] readonly used for non-reassigned fields
227
+ - [ ] const used for constants (not let)
228
+ - [ ] No inline comments (self-explanatory code)
229
+ - [ ] Optional chaining (?.) for safe access
230
+ - [ ] Nullish coalescing (??) for defaults
231
+ - [ ] No `any` types without justification
232
+
233
+ **๐ŸŸข Nice to Have:**
234
+ - [ ] Arrow functions for callbacks
235
+ - [ ] Destructuring for cleaner code
236
+ - [ ] Type guards for type safety
237
+ - [ ] Utility types (Partial, Required, etc.)
238
+
239
+ **Code quality is the foundation - fix these issues before performance optimization.**
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/start.ts","../src/hub-connection.ts","../src/fs-handler.ts","../src/session-manager.ts","../src/skill-loader.ts","../src/brain-bridge.ts","../src/fs-bridge.ts"],"sourcesContent":["import { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { loadConfig, type AgentConfig } from \"./config.js\";\nimport { HubConnection } from \"./hub-connection.js\";\nimport { SessionManager } from \"./session-manager.js\";\nimport { SwarmCoordinator, initRoles } from \"@mclawnet/swarm\";\nimport { initSkills, getSkillList } from \"./skill-loader.js\";\nimport { BrainBridge } from \"./brain-bridge.js\";\nimport { FsBridge } from \"./fs-bridge.js\";\nimport type { BackendAdapter } from \"./backend-adapter.js\";\nimport { createLogger } from \"@mclawnet/logger\";\nimport {\n initDatabase,\n MemoryStore,\n EmbeddingService,\n createEmbeddingProviders,\n distillConversation,\n} from \"@mclawnet/memory\";\nimport {\n SkillStore,\n EvolutionPipeline,\n AccumulationScanner,\n triggerFromAccumulation,\n type MemoryRef,\n} from \"@mclawnet/skill-manager\";\n\nconst log = createLogger({ module: \"agent\" });\n\nexport interface StartOptions {\n config?: Partial<AgentConfig>;\n adapter: BackendAdapter;\n}\n\n/**\n * Start the ClawNet agent: connect to Hub and register a BackendAdapter.\n */\nexport async function startAgent(options: StartOptions): Promise<{\n hub: HubConnection;\n sessionManager: SessionManager;\n swarmCoordinator: SwarmCoordinator;\n brainBridge: BrainBridge;\n fsBridge: FsBridge;\n}> {\n const config = loadConfig(options.config);\n\n if (!config.token) {\n log.error(\"no token configured โ€” set CLAWNET_TOKEN or use --token\");\n process.exit(1);\n }\n\n log.info({ backend: options.adapter.type }, \"starting agent\");\n log.info({ hubUrl: config.hubUrl }, \"connecting to hub\");\n\n // Initialize role templates\n await initRoles();\n\n // Initialize skill system (copy built-in skills + ensure mcp.json)\n await initSkills();\n\n const hub = new HubConnection({\n hubUrl: config.hubUrl,\n token: config.token,\n hostname: config.name,\n onConnect: (agentId) => {\n log.info({ agentId }, \"connected to hub\");\n // Push available skills to browsers via Hub\n const skills = getSkillList();\n if (skills.length > 0) {\n hub.sendSkillList(skills);\n log.info({ count: skills.length }, \"pushed skill list to hub\");\n }\n },\n onDisconnect: (code, reason) => {\n log.info({ code, reason }, \"disconnected from hub\");\n },\n onError: (err) => {\n log.error({ err }, \"hub connection error\");\n },\n });\n\n // Create SwarmCoordinator (needs hub reference; sessionManager set after construction)\n // We use a lazy reference so the coordinator can be created before sessionManager\n let swarmCoordinator: SwarmCoordinator;\n\n // Shared infra for distillation + accumulation scanning on session close\n const clawnetDir = process.env.CLAWNET_DIR ?? join(homedir(), \".clawnet\");\n const dbPath = process.env.CLAWNET_MEMORY_DB ?? join(clawnetDir, \"memory.db\");\n let memoryStore: MemoryStore | null = null;\n let embeddingService: EmbeddingService | null = null;\n let evolutionPipeline: EvolutionPipeline | null = null;\n let skillStore: SkillStore | null = null;\n let memoryDb: ReturnType<typeof initDatabase> | null = null;\n try {\n memoryDb = initDatabase(dbPath);\n memoryStore = new MemoryStore(memoryDb);\n embeddingService = new EmbeddingService(memoryDb, createEmbeddingProviders());\n skillStore = new SkillStore(clawnetDir);\n evolutionPipeline = new EvolutionPipeline(clawnetDir);\n } catch (err) {\n log.warn({ err }, \"failed to init memory/skill infra; distillation disabled\");\n }\n\n const onBeforeClose = async (\n sessionId: string,\n messages: Array<{ role: string; content: string }>,\n ) => {\n if (messages.length === 0) return;\n if (!memoryStore || !embeddingService) return;\n\n // (1) Distill the conversation into role-__assistant__ memories.\n try {\n await distillConversation(\n messages,\n \"role-__assistant__\",\n memoryStore,\n embeddingService,\n );\n } catch (err) {\n log.warn({ err, sessionId }, \"distillation failed (non-fatal)\");\n }\n\n // (2) Scan recent assistant memories for accumulation signals and file\n // Layer-3 proposals against the current Skill set.\n try {\n if (!skillStore || !evolutionPipeline) return;\n const skills = skillStore.scan();\n if (skills.length === 0) return;\n const recent = memoryStore.getMemoriesByRole(\"role-__assistant__\", \"working\");\n const refs: MemoryRef[] = recent.map((m) => ({\n id: m.id,\n type: m.type,\n content: m.content,\n domain: m.domain,\n }));\n const scanner = new AccumulationScanner();\n const signals = scanner.scan(\n refs,\n skills.map((s) => s.name),\n );\n if (signals.length > 0) {\n await triggerFromAccumulation(signals, evolutionPipeline);\n }\n } catch (err) {\n log.warn({ err, sessionId }, \"accumulation scan failed (non-fatal)\");\n }\n };\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 claudeSessionId: info.claudeSessionId,\n cost: info.cost,\n duration: info.duration,\n contextUsage: info.contextUsage,\n });\n },\n onSessionStarted: (sessionId, info) => {\n // Early backfill: tell hub the real claudeSessionId as soon as the\n // backend's `system/init` frame lands. Without this, db's\n // claude_session_id stays NULL until turn_complete โ€” and a mid-turn\n // crash makes the jsonl file unfindable for `--resume`.\n hub.send({\n type: \"claude.session_started\",\n sessionId,\n claudeSessionId: info.claudeSessionId,\n });\n },\n onSessionError: (sessionId, error) => {\n hub.send({\n type: \"session.error\",\n sessionId,\n error,\n });\n },\n onBeforeClose,\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 if (memoryDb) {\n try {\n memoryDb.close();\n } catch (err) {\n log.warn({ err }, \"failed to close memory db\");\n }\n }\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 { 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 AgentSessionDied,\n} from \"@mclawnet/shared\";\nimport type { SessionManager } from \"./session-manager.js\";\nimport type { SwarmCoordinator } from \"@mclawnet/swarm\";\nimport { listRecoverableSwarms, recoverSwarm, listRoles, loadRole, listRecoverableSwarmIds, deleteSwarmSnapshot, listTemplates, loadTemplate } from \"@mclawnet/swarm\";\nimport { handleListDir, handleListFolders, handleListHistorySessions, handleLoadSessionHistory } from \"./fs-handler.js\";\nimport { createLogger, previewFields } from \"@mclawnet/logger\";\n\nconst log = createLogger({ module: \"agent\" });\n\nexport interface HubConnectionOptions {\n hubUrl: string;\n token: string;\n hostname?: string;\n version?: string;\n capabilities?: string[];\n heartbeatInterval?: number;\n reconnectDelay?: number;\n maxReconnectDelay?: number;\n onMessage?: (data: unknown) => void;\n onConnect?: (agentId: string) => void;\n onDisconnect?: (code: number, reason: string) => void;\n onError?: (err: Error) => void;\n}\n\ntype AuthState = \"pending\" | \"authenticating\" | \"authenticated\";\n\nexport class HubConnection {\n private ws: WebSocket | null = null;\n private heartbeatTimer: ReturnType<typeof setInterval> | null = null;\n private reconnectTimer: ReturnType<typeof setTimeout> | null = null;\n private reconnectDelay: number;\n private destroyed = false;\n private authState: AuthState = \"pending\";\n\n readonly hubUrl: string;\n readonly token: string;\n readonly hostname: string;\n readonly version: string | undefined;\n readonly capabilities: string[] | undefined;\n readonly heartbeatInterval: number;\n readonly maxReconnectDelay: number;\n\n /** Agent ID assigned by Hub after successful auth */\n agentId: string | null = null;\n\n /** Swarm IDs that have been completed/failed โ€” prevents accidental recreation */\n private finishedSwarms = new Set<string>();\n\n /** Session manager โ€” set after construction via setSessionManager() */\n private sessionManager: SessionManager | null = null;\n\n /** Swarm coordinator โ€” set after construction via setSwarmCoordinator() */\n private swarmCoordinator: SwarmCoordinator | null = null;\n\n /** Namespace-based generic message handlers */\n private namespaceHandlers = new Map<\n string,\n (msg: AgentGenericRequest) => Promise<Record<string, unknown>>\n >();\n\n private onMessage?: (data: unknown) => void;\n private onConnectCb?: (agentId: string) => void;\n private onDisconnect?: (code: number, reason: string) => void;\n private onError?: (err: Error) => void;\n\n constructor(opts: HubConnectionOptions) {\n this.hubUrl = opts.hubUrl;\n this.token = opts.token;\n this.hostname = opts.hostname ?? osHostname();\n this.version = opts.version;\n this.capabilities = opts.capabilities;\n this.heartbeatInterval = opts.heartbeatInterval ?? HEARTBEAT_INTERVAL_MS;\n this.reconnectDelay = opts.reconnectDelay ?? DEFAULT_RECONNECT_MS;\n this.maxReconnectDelay = opts.maxReconnectDelay ?? MAX_RECONNECT_MS;\n this.onMessage = opts.onMessage;\n this.onConnectCb = opts.onConnect;\n this.onDisconnect = opts.onDisconnect;\n this.onError = opts.onError;\n }\n\n setSessionManager(manager: SessionManager): void {\n this.sessionManager = manager;\n }\n\n setSwarmCoordinator(coordinator: SwarmCoordinator): void {\n this.swarmCoordinator = coordinator;\n }\n\n registerNamespace(\n namespace: string,\n handler: (msg: AgentGenericRequest) => Promise<Record<string, unknown>>\n ) {\n this.namespaceHandlers.set(namespace, handler);\n }\n\n sendPush(namespace: string, event: string, data: Record<string, unknown>) {\n this.send({\n type: \"generic.push\",\n namespace,\n event,\n data,\n });\n }\n\n sendSkillList(skills: Array<{ name: string; description: string }>) {\n this.send({\n type: \"skill_list_update\",\n skills,\n });\n }\n\n get readyState(): number {\n return this.ws?.readyState ?? WebSocket.CLOSED;\n }\n\n get isConnected(): boolean {\n return this.ws?.readyState === WebSocket.OPEN && this.authState === \"authenticated\";\n }\n\n connect(): void {\n if (this.destroyed) return;\n this.cleanupConnection();\n this.authState = \"pending\";\n\n this.ws = new WebSocket(this.hubUrl);\n\n this.ws.on(\"open\", () => {\n this.reconnectDelay = DEFAULT_RECONNECT_MS;\n });\n\n this.ws.on(\"message\", (raw) => {\n let data: AgentServerMessage;\n try {\n data = JSON.parse(raw.toString());\n } catch {\n return;\n }\n\n // Step 1: Hub sends auth_required โ†’ reply with auth\n if (this.authState === \"pending\" && data.type === \"auth_required\") {\n log.info(\"hub requires auth, sending credentials\");\n this.authState = \"authenticating\";\n this.sendRaw({\n type: \"auth\",\n token: this.token,\n hostname: this.hostname,\n version: this.version,\n capabilities: this.capabilities,\n });\n return;\n }\n\n // Step 2: Hub sends registered โ†’ auth complete\n if (this.authState === \"authenticating\" && data.type === \"registered\") {\n log.info({ agentId: data.agentId }, \"registered with hub\");\n this.authState = \"authenticated\";\n this.agentId = data.agentId ?? null;\n this.startHeartbeat();\n this.onConnectCb?.(this.agentId!);\n\n // Attempt to recover any persisted swarms\n this.tryRecoverSwarms();\n\n // Report any sessions that survived reconnect to Hub\n this.reportLiveSessions();\n return;\n }\n\n // Post-auth message handling\n if (this.authState === \"authenticated\") {\n if (this.handleSessionMessage(data)) return;\n this.onMessage?.(data);\n }\n });\n\n this.ws.on(\"close\", (code, reason) => {\n log.warn({ code, reason: reason.toString() }, \"disconnected from hub\");\n this.stopHeartbeat();\n this.authState = \"pending\";\n this.onDisconnect?.(code, reason.toString());\n if (code === WS_CLOSE_INVALID_TOKEN) {\n log.error(\"auth failed โ€” not reconnecting, check your token\");\n return;\n }\n this.scheduleReconnect();\n });\n\n this.ws.on(\"error\", (err) => {\n log.error({ err }, \"ws connection error\");\n this.onError?.(err);\n });\n }\n\n send(data: AgentClientMessage): boolean {\n // Track swarm completion to prevent accidental recreation\n const msg = data as any;\n if (msg.type === \"swarm.status\" && (msg.swarmStatus === \"completed\" || msg.swarmStatus === \"failed\")) {\n this.finishedSwarms.add(msg.sessionId);\n }\n return this.sendRaw(data);\n }\n\n destroy(): void {\n this.destroyed = true;\n this.cleanup();\n }\n\n // โ”€โ”€ Session message handling โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n\n private handleSessionMessage(msg: AgentServerMessage): boolean {\n // โ”€โ”€ Filesystem / history requests (no sessionManager needed) โ”€โ”€โ”€โ”€โ”€\n\n if (msg.type === \"fs.list_dir\") {\n log.info({ path: msg.path }, \"fs.list_dir\");\n handleListDir(msg.path)\n .then((result) => {\n this.send({ type: \"fs.list_dir_result\", requestId: msg.requestId, ...result });\n })\n .catch((err: any) => {\n log.error({ err, path: msg.path }, \"fs.list_dir failed\");\n this.send({\n type: \"fs.list_dir_result\",\n requestId: msg.requestId,\n path: msg.path || \"/\",\n entries: [],\n });\n });\n return true;\n }\n\n if (msg.type === \"list_folders\") {\n log.info(\"list_folders\");\n handleListFolders()\n .then((result) => {\n this.send({ type: \"folders_list_result\", requestId: msg.requestId, ...result });\n })\n .catch((err: any) => {\n log.error({ err }, \"list_folders failed\");\n this.send({ type: \"folders_list_result\", requestId: msg.requestId, folders: [] });\n });\n return true;\n }\n\n if (msg.type === \"list_history_sessions\") {\n log.info({ workDir: msg.workDir }, \"list_history_sessions\");\n handleListHistorySessions(msg.workDir)\n .then((result) => {\n this.send({ type: \"history_sessions_result\", requestId: msg.requestId, ...result });\n })\n .catch((err: any) => {\n log.error({ err, workDir: msg.workDir }, \"list_history_sessions failed\");\n this.send({\n type: \"history_sessions_result\",\n requestId: msg.requestId,\n workDir: msg.workDir,\n sessions: [],\n });\n });\n return true;\n }\n\n if (msg.type === \"load_session_history\") {\n log.info(\n { workDir: msg.workDir, claudeSessionId: msg.claudeSessionId, before: msg.before, limit: msg.limit },\n \"load_session_history\",\n );\n handleLoadSessionHistory(msg.workDir, msg.claudeSessionId, { before: msg.before, limit: msg.limit })\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: [], oldestSeq: 0, hasMore: false });\n });\n return true;\n }\n\n // โ”€โ”€ Swarm handling (requires swarmCoordinator) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n\n if (msg.type === \"list_roles\") {\n log.info(\"list_roles\");\n const roleNames = listRoles();\n const roles = roleNames.map((name) => {\n try {\n const def = loadRole(name);\n return {\n name: def.name,\n displayName: def.displayName || def.description || def.name,\n description: def.description || \"\",\n capabilities: def.capabilities || [],\n type: def.type,\n color: def.color,\n promptBody: def.promptBody || \"\",\n };\n } catch {\n return { name, displayName: name, description: \"\", capabilities: [], promptBody: \"\" };\n }\n });\n this.send({\n type: \"roles_list_result\",\n sessionId: (msg as any).sessionId,\n roles,\n } as any);\n return true;\n }\n\n if (msg.type === \"list_templates\") {\n log.info(\"list_templates\");\n try {\n const names = listTemplates();\n const templates = names.map((name) => {\n const tpl = loadTemplate(name);\n return {\n name: tpl.name,\n displayName: tpl.displayName,\n description: tpl.description,\n icon: tpl.icon,\n roles: tpl.roles,\n };\n });\n this.send({\n type: \"templates_list_result\",\n sessionId: (msg as any).sessionId,\n templates,\n } as any);\n } catch (err) {\n log.error({ err }, \"list_templates failed\");\n this.send({\n type: \"templates_list_result\",\n sessionId: (msg as any).sessionId,\n templates: [],\n } as any);\n }\n return true;\n }\n\n // โ”€โ”€ Generic request: dispatch to registered namespace handlers โ”€โ”€\n if (msg.type === \"generic.request\") {\n const handler = this.namespaceHandlers.get(msg.namespace);\n if (handler) {\n log.info({ namespace: msg.namespace, action: msg.action, requestId: msg.requestId }, \"generic.request received\");\n handler(msg)\n .then((result) => {\n log.info({ namespace: msg.namespace, action: msg.action, requestId: msg.requestId }, \"generic.request handled OK\");\n this.send({\n type: \"generic.response\",\n namespace: msg.namespace,\n action: msg.action,\n data: result,\n requestId: msg.requestId,\n });\n })\n .catch((err) => {\n log.error({ namespace: msg.namespace, action: msg.action, requestId: msg.requestId, err }, \"generic.request handler error\");\n this.send({\n type: \"generic.response\",\n namespace: msg.namespace,\n action: msg.action,\n data: {},\n requestId: msg.requestId,\n error: err instanceof Error ? err.message : String(err),\n });\n });\n return true;\n }\n log.warn({ namespace: msg.namespace, action: msg.action, requestId: msg.requestId }, \"generic.request unknown namespace\");\n this.send({\n type: \"generic.response\",\n namespace: msg.namespace,\n action: msg.action,\n data: {},\n requestId: msg.requestId,\n error: `Unknown namespace: ${msg.namespace}`,\n });\n return true;\n }\n\n if (msg.type === \"swarm.execute\" && this.swarmCoordinator) {\n const { sessionId, content, workDir, targetInstance, crewConfig } = msg;\n\n if (this.swarmCoordinator.hasSwarm(sessionId)) {\n // Existing swarm โ€” forward user message\n log.info({ sessionId, targetInstance }, \"swarm.execute: forwarding to existing swarm\");\n this.swarmCoordinator.handleUserMessage(sessionId, content, targetInstance).catch((err) => {\n this.send({\n type: \"session.error\",\n sessionId,\n error: err instanceof Error ? err.message : String(err),\n });\n });\n } else if (this.finishedSwarms.has(sessionId)) {\n // Swarm completed/failed โ€” recreate to continue if config available\n if (crewConfig?.templateName || crewConfig?.roles) {\n this.finishedSwarms.delete(sessionId);\n const templateName = crewConfig.templateName;\n const roles = crewConfig.roles;\n log.info({ sessionId, templateName, rolesCount: roles?.length }, \"swarm.execute: continuing finished swarm\");\n this.swarmCoordinator.create(sessionId, { workDir, templateName, roles, task: content, isContinuation: true }).catch((err) => {\n this.send({\n type: \"session.error\",\n sessionId,\n error: err instanceof Error ? err.message : String(err),\n });\n });\n } else {\n log.info({ sessionId }, \"swarm.execute ignored: swarm finished, no config to recreate\");\n this.send({\n type: \"session.error\",\n sessionId,\n error: \"่œ‚็พคไปปๅŠกๅทฒๅฎŒๆˆไธ”ๆ— ๆณ•ๆขๅค้…็ฝฎใ€‚่ฏทๅˆ›ๅปบๆ–ฐ็š„่œ‚็พคไปปๅŠกใ€‚\",\n });\n }\n } else if (crewConfig?.templateName || crewConfig?.roles) {\n // Create new swarm: template-based or direct roles\n const templateName = crewConfig.templateName;\n const roles = crewConfig.roles;\n log.info({ sessionId, templateName, rolesCount: roles?.length }, \"swarm.execute: creating new swarm\");\n this.swarmCoordinator.create(sessionId, { workDir, templateName, roles, task: content }).catch((err) => {\n this.send({\n type: \"session.error\",\n sessionId,\n error: err instanceof Error ? err.message : String(err),\n });\n });\n } else {\n // No swarm and no crewConfig โ€” shouldn't happen normally\n log.info({ sessionId }, \"swarm.execute ignored: swarm not found, no config\");\n this.send({\n type: \"session.error\",\n sessionId,\n error: \"่œ‚็พคไปปๅŠกๅทฒๅฎŒๆˆ๏ผŒๆ— ๆณ•็ปง็ปญๆ“ไฝœใ€‚่ฏทๅˆ›ๅปบๆ–ฐ็š„่œ‚็พคไปปๅŠกใ€‚\",\n });\n }\n return true;\n }\n\n // โ”€โ”€ Session management (requires sessionManager) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n\n if (!this.sessionManager) return false;\n\n if (msg.type === \"abort_execution\") {\n const { sessionId } = msg;\n log.info({ sessionId }, \"abort_execution\");\n if (this.sessionManager?.hasSession(sessionId)) {\n this.sessionManager.abortSession(sessionId).then(() => {\n this.send({ type: \"execution_aborted\", sessionId } as any);\n }).catch(() => {\n this.send({ type: \"execution_aborted\", sessionId } as any);\n });\n } else {\n // No active session โ€” just acknowledge\n this.send({ type: \"execution_aborted\", sessionId } as any);\n }\n return true;\n }\n\n // claude.execute โ€” auto-create session if needed, then send input.\n // Three branches:\n // 1. healthy reuse โ€” process alive, write directly\n // 2. unhealthy + db has claudeSessionId โ€” abort residue, spawn --resume\n // and notify hub via session.died so it can flush stale turnBuffer\n // 3. brand new โ€” original create path\n if (msg.type === \"claude.execute\") {\n const { sessionId, content, workDir, claudeSessionId, useBrainCore } = msg;\n const sm = this.sessionManager;\n\n const spawnAndSend = (resumeId: string | undefined, label: string) => {\n log.info({ sessionId, claudeSessionId: resumeId, workDir, label }, \"claude.execute: spawning\");\n log.debug({ sessionId, ...previewFields(content) }, \"claude.execute: input\");\n sm.createSession({ sessionId, workDir, resumeId, useBrainCore, roleId: \"role-__assistant__\" })\n .then(() => {\n sm.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\n if (sm.isHealthy(sessionId)) {\n log.info({ sessionId }, \"claude.execute: reusing healthy session\");\n log.debug({ sessionId, ...previewFields(content) }, \"claude.execute: input\");\n sm.sendInput(sessionId, content);\n } else if (sm.hasSession(sessionId) && claudeSessionId) {\n // Map entry exists but process is dead (exit handler may not have\n // fired yet, or stdin closed). Tear down and respawn via --resume.\n // Notify hub first so it can flush the orphan turnBuffer before the\n // new session's first chunk arrives.\n log.warn({ sessionId, claudeSessionId }, \"claude.execute: session unhealthy, recreating with --resume\");\n this.send({\n type: \"session.died\",\n sessionId,\n reason: \"unhealthy_before_input\",\n } satisfies AgentSessionDied);\n sm.abortSession(sessionId)\n .catch((err) => {\n // Don't bail โ€” log and continue; createSession below will surface\n // any real failure. Silent swallow used to mask \"two children racing\n // on the same sessionId\" bugs.\n log.warn({ sessionId, err: err instanceof Error ? err.message : String(err) }, \"abortSession failed during unhealthy fallback, proceeding to respawn\");\n })\n .then(() => spawnAndSend(claudeSessionId, \"unhealthy_fallback_resume\"));\n } else if (claudeSessionId) {\n // No live process but db has claudeSessionId โ†’ resume from disk\n spawnAndSend(claudeSessionId, \"fresh_resume\");\n } else {\n spawnAndSend(undefined, \"brand_new\");\n }\n return true;\n }\n\n // session.force_restart โ€” hub detected stuck session and asked agent to\n // tear it down. Agent aborts and replies with session.died so hub can\n // flush turnBuffer; the next claude.execute will go through the unhealthy\n // fallback above and respawn via --resume.\n if (msg.type === \"session.force_restart\") {\n const { sessionId, reason } = msg;\n log.warn({ sessionId, reason }, \"session.force_restart received\");\n const sm = this.sessionManager;\n const reply: AgentSessionDied = {\n type: \"session.died\",\n sessionId,\n reason: reason ?? \"force_restart\",\n };\n if (sm.hasSession(sessionId)) {\n sm.abortSession(sessionId)\n .catch((err) => {\n log.warn({ sessionId, err: err instanceof Error ? err.message : String(err) }, \"abortSession failed during force_restart\");\n })\n .finally(() => {\n this.send(reply);\n });\n } else {\n this.send(reply);\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.debug(\n { sessionId: msg.sessionId, ...previewFields(msg.content) },\n \"claude.input\",\n );\n this.sessionManager.sendInput(msg.sessionId, msg.content);\n return true;\n }\n\n return false;\n }\n\n // โ”€โ”€ Internal helpers โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n\n private tryRecoverSwarms(): void {\n if (!this.swarmCoordinator) return;\n try {\n const allIds = listRecoverableSwarmIds();\n const snapshots = listRecoverableSwarms();\n const recoverableIds = new Set(snapshots.map((s) => s.id));\n\n // Clean up expired/completed/failed snapshots\n for (const id of allIds) {\n if (!recoverableIds.has(id)) {\n deleteSwarmSnapshot(id);\n log.info({ swarmId: id }, \"cleaned up non-recoverable swarm snapshot\");\n }\n }\n\n for (const snap of snapshots) {\n log.info({ swarmId: snap.id }, \"recovering swarm\");\n recoverSwarm(this.swarmCoordinator, snap).catch((err) => {\n log.error({ err, swarmId: snap.id }, \"failed to recover swarm\");\n });\n }\n } catch (err) {\n log.error({ err }, \"swarm recovery failed\");\n }\n }\n\n private reportLiveSessions(): void {\n if (!this.sessionManager) return;\n const ids = this.sessionManager.getActiveSessionIds();\n if (ids.length === 0) return;\n log.info({ count: ids.length }, \"reporting live sessions to hub after reconnect\");\n for (const sessionId of ids) {\n this.send({\n type: \"session.state\",\n sessionId,\n processState: \"ready\",\n });\n }\n }\n\n private sendRaw(data: unknown): boolean {\n if (!this.ws || this.ws.readyState !== WebSocket.OPEN) return false;\n this.ws.send(JSON.stringify(data));\n return true;\n }\n\n private startHeartbeat(): void {\n this.stopHeartbeat();\n this.heartbeatTimer = setInterval(() => {\n this.send({ type: \"heartbeat\", ts: Date.now() });\n }, this.heartbeatInterval);\n }\n\n private stopHeartbeat(): void {\n if (this.heartbeatTimer) {\n clearInterval(this.heartbeatTimer);\n this.heartbeatTimer = null;\n }\n }\n\n private scheduleReconnect(): void {\n if (this.destroyed) return;\n log.warn({ delayMs: this.reconnectDelay }, \"reconnecting to hub...\");\n this.reconnectTimer = setTimeout(() => {\n this.connect();\n }, this.reconnectDelay);\n this.reconnectDelay = Math.min(this.reconnectDelay * 2, this.maxReconnectDelay);\n }\n\n private cleanup(): void {\n this.cleanupConnection();\n this.sessionManager?.closeAll().catch(() => {});\n }\n\n private cleanupConnection(): void {\n this.stopHeartbeat();\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = null;\n }\n if (this.ws) {\n this.ws.removeAllListeners();\n if (this.ws.readyState === WebSocket.OPEN || this.ws.readyState === WebSocket.CONNECTING) {\n this.ws.close();\n }\n this.ws = null;\n }\n }\n}\n","import { readdir, stat, readFile } from \"node:fs/promises\";\nimport { existsSync, readdirSync, statSync, readFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\n\nconst SKIP_DIRS = new Set([\".git\", \"node_modules\", \"__pycache__\", \".next\", \".nuxt\", \".cache\"]);\n\n// โ”€โ”€ fs.list_dir โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n\nexport async function handleListDir(\n path: string,\n): Promise<{ path: string; entries: Array<{ name: string; type: \"directory\" | \"file\" }> }> {\n const target = path || homedir();\n const dirents = await readdir(target, { withFileTypes: true });\n\n const entries = dirents\n .filter((d) => !(d.isDirectory() && SKIP_DIRS.has(d.name)))\n .map((d) => ({\n name: d.name,\n type: (d.isDirectory() ? \"directory\" : \"file\") as \"directory\" | \"file\",\n }))\n .sort((a, b) => {\n if (a.type !== b.type) return a.type === \"directory\" ? -1 : 1;\n return a.name.localeCompare(b.name);\n });\n\n return { path: target, entries };\n}\n\n// โ”€โ”€ list_folders (scan ~/.claude/projects/) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n\nfunction getClaudeProjectsDir(): string {\n return join(homedir(), \".claude\", \"projects\");\n}\n\nfunction pathToProjectFolder(workDir: string): string {\n return workDir.replace(/:/g, \"-\").replace(/[/\\\\]/g, \"-\");\n}\n\nfunction extractWorkDirFromSessionFile(filePath: string): string | null {\n try {\n const content = readFileSync(filePath, \"utf-8\");\n const lines = content.split(\"\\n\").filter((l) => l.trim());\n for (const line of lines.slice(0, 5)) {\n try {\n const data = JSON.parse(line);\n if (data.cwd) return data.cwd.replace(/\\\\/g, \"/\");\n } catch {}\n }\n } catch {}\n return null;\n}\n\nfunction getWorkDirFromProjectFolder(folderPath: string, folderName: string): string {\n try {\n const files = readdirSync(folderPath);\n for (const file of files) {\n if (file.endsWith(\".jsonl\")) {\n const workDir = extractWorkDirFromSessionFile(join(folderPath, file));\n if (workDir) return workDir;\n }\n }\n } catch {}\n\n // Fallback: simple conversion\n if (/^[A-Za-z]--/.test(folderName)) {\n return folderName.replace(/^([A-Za-z])--/, \"$1:/\").replace(/-/g, \"/\");\n }\n if (folderName.startsWith(\"-\")) {\n return \"/\" + folderName.substring(1).replace(/-/g, \"/\");\n }\n return folderName.replace(/-/g, \"/\");\n}\n\nexport async function handleListFolders(): Promise<{\n folders: Array<{ path: string; sessionCount: number; lastModified?: number }>;\n}> {\n const projectsDir = getClaudeProjectsDir();\n const folders: Array<{ path: string; sessionCount: number; lastModified?: number }> = [];\n\n if (!existsSync(projectsDir)) return { folders };\n\n const entries = readdirSync(projectsDir);\n for (const entry of entries) {\n const entryPath = join(projectsDir, entry);\n let entryStat;\n try {\n entryStat = statSync(entryPath);\n } catch {\n continue;\n }\n if (!entryStat.isDirectory()) continue;\n\n // Skip crew role directories\n if (entry.includes(\"--crew-roles-\")) continue;\n\n const originalPath = getWorkDirFromProjectFolder(entryPath, entry);\n\n let sessionCount = 0;\n let lastModified = entryStat.mtime.getTime();\n\n try {\n const files = readdirSync(entryPath);\n for (const file of files) {\n if (file.endsWith(\".jsonl\")) {\n sessionCount++;\n try {\n const fileStats = statSync(join(entryPath, file));\n if (fileStats.mtime.getTime() > lastModified) {\n lastModified = fileStats.mtime.getTime();\n }\n } catch {}\n }\n }\n } catch {}\n\n folders.push({ path: originalPath, sessionCount, lastModified });\n }\n\n folders.sort((a, b) => (b.lastModified ?? 0) - (a.lastModified ?? 0));\n return { folders };\n}\n\n// โ”€โ”€ list_history_sessions โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n\nexport async function handleListHistorySessions(workDir: string): Promise<{\n workDir: string;\n sessions: Array<{ sessionId: string; title: string; workDir?: string; lastModified?: number }>;\n}> {\n const projectsDir = getClaudeProjectsDir();\n const projectFolder = pathToProjectFolder(workDir);\n const projectPath = join(projectsDir, projectFolder);\n\n if (!existsSync(projectPath)) {\n return { workDir, sessions: [] };\n }\n\n const sessions: Array<{ sessionId: string; title: string; workDir?: string; lastModified?: number }> = [];\n const files = readdirSync(projectPath);\n\n for (const file of files) {\n if (!file.endsWith(\".jsonl\")) continue;\n\n const sessionId = file.replace(\".jsonl\", \"\");\n const filePath = join(projectPath, file);\n let fileStats;\n try {\n fileStats = statSync(filePath);\n } catch {\n continue;\n }\n\n let title = \"\";\n let hasUserMessage = false;\n let customTitle = \"\";\n let jsonlSummary = \"\";\n\n try {\n const content = readFileSync(filePath, \"utf-8\");\n const lines = content.split(\"\\n\").filter((l) => l.trim());\n\n for (const line of lines) {\n try {\n const data = JSON.parse(line);\n if (!hasUserMessage && data.type === \"user\" && data.message?.content) {\n const text =\n typeof data.message.content === \"string\"\n ? data.message.content\n : data.message.content[0]?.text || \"\";\n if (text.trim()) {\n title = text.substring(0, 100);\n hasUserMessage = true;\n }\n }\n if (data.type === \"custom-title\" && data.customTitle) {\n customTitle = data.customTitle;\n }\n if (data.type === \"summary\" && data.summary) {\n jsonlSummary = data.summary;\n }\n } catch {}\n }\n } catch {}\n\n if (hasUserMessage) {\n sessions.push({\n sessionId,\n title: customTitle || jsonlSummary || title || sessionId.slice(0, 8),\n workDir,\n lastModified: fileStats.mtime.getTime(),\n });\n }\n }\n\n sessions.sort((a, b) => (b.lastModified ?? 0) - (a.lastModified ?? 0));\n return { workDir, sessions };\n}\n\n// โ”€โ”€ load_session_history โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n\ninterface HistoryMessage {\n role: \"user\" | \"assistant\";\n content: string;\n toolCalls?: Array<{ name: string; input?: string; output?: string; status: string }>;\n thinking?: string;\n}\n\n/**\n * Load message history from a Claude jsonl file.\n *\n * Pagination contract:\n * - `seq` is the index into the post-filter messages array (NOT raw jsonl\n * line number). Filtering is a pure function of the file contents, so\n * a given (file, fs-handler version) pair always yields the same\n * mapping. jsonl is append-only โ€” new assistant turns only ever\n * extend the array, so a seq captured by the browser remains valid.\n * - `before`: return messages with seq < before. Omit/0 = newest tail.\n * - `limit`: max messages returned. Default 50.\n * - `oldestSeq`: seq of the FIRST message in the returned slice. The\n * browser passes this as `before` on the next \"load earlier\" request.\n * - `hasMore`: true iff oldestSeq > 0 (older messages exist on disk).\n *\n * Caveat: changes to the filter rules below (added/removed block types)\n * invalidate any cached seq across all clients. Treat as a protocol-level\n * breaking change โ€” bump shared protocol version when modifying.\n */\nexport async function handleLoadSessionHistory(\n workDir: string,\n claudeSessionId: string,\n opts?: { before?: number; limit?: number },\n): Promise<{ messages: HistoryMessage[]; oldestSeq: number; hasMore: boolean }> {\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: [], oldestSeq: 0, hasMore: false };\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 const limit = Math.max(1, Math.min(opts?.limit ?? 50, 200));\n // `before` semantics: return messages with seq < before. When omitted,\n // tail-load (newest `limit`).\n const upper = opts?.before === undefined || opts.before <= 0 || opts.before > messages.length\n ? messages.length\n : opts.before;\n const lower = Math.max(0, upper - limit);\n const slice = messages.slice(lower, upper);\n return {\n messages: slice,\n oldestSeq: lower,\n hasMore: lower > 0,\n };\n}\n","import { createLogger, previewFields } from \"@mclawnet/logger\";\nimport { buildMemorySection } from \"@mclawnet/memory\";\nimport { getPendingNotification } from \"./skill-loader.js\";\nimport type { BackendAdapter, BackendProcess, SpawnOptions } from \"./backend-adapter.js\";\n\nconst log = createLogger({ module: \"agent/session-manager\" });\n\nconst DEFAULT_MAX_PROCESSES = 10;\nconst MAX_PROCESSES = Number(process.env.CLAWNET_MAX_PROCESSES) || DEFAULT_MAX_PROCESSES;\n\n/**\n * Manages active sessions, mapping ClawNet session IDs to BackendProcess instances.\n *\n * When `options.roleId` is set, the manager automatically injects:\n * - Pipeline A: memory prompt + roleId hint via `--append-system-prompt`\n *\n * Note: MCP config is now handled globally via ~/.clawnet/mcp.json\n * (mounted by ClaudeCodeAdapter), no longer generated per-session.\n */\nexport class SessionManager {\n private sessions = new Map<string, BackendProcess>();\n private conversationBuffer = new Map<string, Array<{ role: string; content: string }>>();\n // Sessions whose abort is in flight. Treated as not-present by hasSession /\n // isHealthy so a racing claude.execute (e.g., right after force_restart) is\n // correctly routed to the \"spawn new + --resume\" branch instead of trying\n // to write to a process we are about to kill.\n private aborting = new Set<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 onSessionStarted?: (sessionId: string, info: { claudeSessionId: 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 onSessionStarted?: (sessionId: string, info: { claudeSessionId: 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.onSessionStarted = options.onSessionStarted;\n this.onBeforeClose = options.onBeforeClose;\n }\n\n async createSession(options: SpawnOptions): Promise<string> {\n if (this.sessions.has(options.sessionId)) {\n throw new Error(`Session ${options.sessionId} already exists`);\n }\n\n if (this.sessions.size >= MAX_PROCESSES) {\n throw new Error(`Process limit reached (${MAX_PROCESSES}). Cannot create new session.`);\n }\n\n // โ”€โ”€ Unified memory injection โ”€โ”€\n if (options.roleId) {\n // Pipeline A: prepend memory section + roleId hint to system prompt\n try {\n const memorySection = buildMemorySection(options.roleId);\n const roleHint = `\\n\\n[Memory Context] Your roleId is \"${options.roleId}\". Always use this roleId when calling memory_search, memory_store, memory_stats, or memory_reflect.`;\n options.systemPrompt = options.systemPrompt\n ? `${memorySection}${roleHint}\\n\\n${options.systemPrompt}`\n : `${memorySection}${roleHint}`;\n log.debug({ roleId: options.roleId, sessionId: options.sessionId }, \"memory prompt + roleId hint injected\");\n } catch (err) {\n log.warn({ err, roleId: options.roleId }, \"failed to build memory section, proceeding without\");\n }\n }\n\n // โ”€โ”€ Pending skill-evolution notification โ”€โ”€\n try {\n const notice = getPendingNotification();\n if (notice) {\n const noticeBlock = `\\n\\n[Skill ่ฟ›ๅŒ–ๆๆกˆ]\\n${notice.text}`;\n options.systemPrompt = options.systemPrompt\n ? `${options.systemPrompt}${noticeBlock}`\n : noticeBlock.trimStart();\n log.debug(\n { sessionId: options.sessionId, pending: notice.count },\n \"pending skill evolution notice injected\",\n );\n }\n } catch (err) {\n log.debug({ err }, \"failed to inject pending notification\");\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 // Wire up early session-started handler โ€” Claude CLI emits its real\n // session_id in the first `system/init` frame, well before turn_complete.\n // Persisting it immediately means a mid-turn crash still leaves db\n // pointing at the correct jsonl file for `--resume`.\n //\n // B2 race guard: stdout buffered before SIGTERM lands can still emit\n // `system/init` after we've decided to abort. Suppress those late frames\n // so hub doesn't resurrect a dead session's claudeSessionId / spinner.\n if (this.onSessionStarted) {\n this.adapter.onSessionStarted?.(process, (info) => {\n if (this.aborting.has(options.sessionId)) {\n log.debug(\n { sessionId: options.sessionId },\n \"suppressing late session_started โ€” session is aborting\",\n );\n return;\n }\n if (this.sessions.get(options.sessionId) !== process) {\n // Map already swapped to a fresh process for this sessionId โ€” the\n // event belongs to the previous, now-orphaned process.\n return;\n }\n this.onSessionStarted!(options.sessionId, info);\n });\n }\n\n // Auto-evict on unexpected exit (crash, EPIPE, OOM, external SIGKILL).\n // Without this, hasSession() keeps returning true after the child dies\n // and reuse path writes to a dead pipe โ€” root cause of the \"stuck\n // session\" symptom this PR fixes.\n this.adapter.onExit?.(process, (code) => {\n if (this.sessions.get(options.sessionId) === process) {\n this.sessions.delete(options.sessionId);\n this.conversationBuffer.delete(options.sessionId);\n log.warn({ sessionId: options.sessionId, exitCode: code }, \"backend process exited unexpectedly, evicted from session map\");\n this.onSessionError(options.sessionId, `backend process exited (code=${code ?? \"null\"})`);\n }\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 log.debug(\n { sessionId, ...previewFields(input) },\n \"sendInput โ†’ backend stdin\",\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 // Mark aborting *before* awaiting stop() so concurrent isHealthy / hasSession\n // calls immediately see the session as gone โ€” fixes the race where hub\n // sends force_restart and claude.execute back-to-back.\n this.aborting.add(sessionId);\n this.conversationBuffer.delete(sessionId);\n this.sessions.delete(sessionId);\n try {\n await this.adapter.stop(process);\n } finally {\n this.aborting.delete(sessionId);\n }\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) && !this.aborting.has(sessionId);\n }\n\n /**\n * Stricter than hasSession(): also requires the underlying process to still\n * be alive (not exited, stdin still writable). Callers in the reuse path\n * must use this to avoid sending input into a dead pipe โ€” if it returns\n * false they should fall back to `--resume` against db's claudeSessionId.\n */\n isHealthy(sessionId: string): boolean {\n if (this.aborting.has(sessionId)) return false;\n const process = this.sessions.get(sessionId);\n return !!process && process.isAlive();\n }\n\n get activeSessionCount(): number {\n return this.sessions.size;\n }\n\n getActiveSessionIds(): string[] {\n return Array.from(this.sessions.keys());\n }\n}\n","import { existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { createHash } from \"node:crypto\";\nimport { join, dirname } from \"node:path\";\nimport { homedir } from \"node:os\";\nimport { createRequire } from \"node:module\";\nimport { fileURLToPath } from \"node:url\";\nimport { createLogger } from \"@mclawnet/logger\";\nimport { ManifestManager, mergeSkillSections } from \"@mclawnet/skill-manager\";\n\nconst log = createLogger({ module: \"agent/skill-loader\" });\n\n/** ~/.clawnet base directory */\nconst CLAWNET_DIR = join(homedir(), \".clawnet\");\n/** Skill target directory: ~/.clawnet/.claude/skills/ */\nconst SKILLS_DIR = join(CLAWNET_DIR, \".claude\", \"skills\");\n/** MCP config file: ~/.clawnet/mcp.json */\nconst MCP_CONFIG_PATH = join(CLAWNET_DIR, \"mcp.json\");\n\n/**\n * Initialize ClawNet skill system:\n * 1. Ensure skill directory exists\n * 2. Sync built-in skills via the manifest (three-way merge aware)\n * 3. Ensure MCP config exists\n */\nexport async function initSkills(): Promise<void> {\n ensureSkillsDir();\n syncBuiltinSkills(CLAWNET_DIR, defaultBuiltinSourceDir());\n ensureMcpConfig();\n scanSkills();\n}\n\n/** Built-in skills live next to the agent's compiled output at `../skills`. */\nfunction defaultBuiltinSourceDir(): string {\n const thisFile = fileURLToPath(import.meta.url);\n return join(dirname(thisFile), \"..\", \"skills\");\n}\n\nfunction sha256(s: string): string {\n return createHash(\"sha256\").update(s).digest(\"hex\");\n}\n\n/** Read version from built-in skill frontmatter (defaults to 1.0.0). */\nfunction readBuiltinVersion(content: string): string {\n const match = content.match(/^version:\\s*(.+)$/m);\n return match ? match[1].trim().replace(/^[\"']|[\"']$/g, \"\") : \"1.0.0\";\n}\n\n/**\n * Synchronize built-in skills into `rootDir/.claude/skills` using the\n * manifest so user edits are preserved across official upgrades:\n *\n * - brand-new skill โ†’ install + register in manifest\n * - user unchanged, official changed โ†’ overwrite + update manifest\n * - user changed, official unchanged โ†’ skip (nothing to do)\n * - both changed โ†’ attempt section-level 3-way merge; on conflict write\n * a `SKILL.md.conflict` sibling file and leave user copy untouched.\n */\nexport function syncBuiltinSkills(rootDir: string, srcDir: string): void {\n const skillsDir = join(rootDir, \".claude\", \"skills\");\n if (!existsSync(skillsDir)) mkdirSync(skillsDir, { recursive: true });\n\n if (!existsSync(srcDir)) {\n log.debug({ srcDir }, \"no built-in skills directory found, skipping\");\n return;\n }\n\n const manifest = new ManifestManager(rootDir);\n\n let entries: string[];\n try {\n entries = readdirSync(srcDir, { withFileTypes: true })\n .filter((d) => d.isDirectory())\n .map((d) => d.name);\n } catch {\n log.warn({ srcDir }, \"failed to read built-in skills directory\");\n return;\n }\n\n for (const skillName of entries) {\n const srcSkillMd = join(srcDir, skillName, \"SKILL.md\");\n if (!existsSync(srcSkillMd)) continue;\n\n const destDir = join(skillsDir, skillName);\n const destSkillMd = join(destDir, \"SKILL.md\");\n const baseSnapshotPath = join(destDir, \".base.md\");\n\n let officialContent: string;\n try {\n officialContent = readFileSync(srcSkillMd, \"utf-8\");\n } catch (err) {\n log.warn({ skill: skillName, err }, \"failed to read built-in skill\");\n continue;\n }\n const officialHash = sha256(officialContent);\n const officialVersion = readBuiltinVersion(officialContent);\n\n // Brand new skill on this machine\n if (!existsSync(destSkillMd)) {\n try {\n mkdirSync(destDir, { recursive: true });\n writeFileSync(destSkillMd, officialContent);\n writeFileSync(baseSnapshotPath, officialContent);\n manifest.register(skillName, officialHash, officialVersion);\n log.info({ skill: skillName, version: officialVersion }, \"installed built-in skill\");\n } catch (err) {\n log.warn({ skill: skillName, err }, \"failed to install built-in skill\");\n }\n continue;\n }\n\n // Existing skill โ€” consult manifest\n const userContent = readFileSync(destSkillMd, \"utf-8\");\n const userHash = sha256(userContent);\n manifest.refresh(skillName, userHash);\n\n // ๆƒฐๆ€งๅ›žๅกซ .base.md๏ผš่‹ฅไน‹ๅ‰็‰ˆๆœฌๆฒกๅ†™่ฟ‡๏ผŒ่€Œ็”จๆˆทไปŽๆœชๆ”นๅŠจ๏ผˆuserHash ไธŽ\n // manifest ่ฎฐๅฝ•็š„ baseHash ไธ€่‡ด๏ผ‰๏ผŒๅˆ™ๅฝ“ๅ‰็”จๆˆทๅ†…ๅฎนๅณไธบไธŠๆฌกๅฎ˜ๆ–น็‰ˆๆœฌ๏ผŒ\n // ๅฏไปฅ็›ดๆŽฅไฝœไธบ base ๅฟซ็…ง๏ผŒไธบๆœชๆฅ็š„ไธ‰ๆ–นๅˆๅนถๆ‰“ไธ‹ๅŸบ็ก€ใ€‚\n if (!existsSync(baseSnapshotPath)) {\n const entry = manifest.load().skills[skillName];\n if (entry && !entry.userModified) {\n try {\n writeFileSync(baseSnapshotPath, userContent);\n } catch (err) {\n log.debug({ skill: skillName, err }, \"failed to write lazy .base.md\");\n }\n }\n }\n\n const action = manifest.determineSyncAction(skillName, officialHash, officialVersion);\n switch (action) {\n case \"skip\":\n log.debug({ skill: skillName }, \"skill already up to date\");\n break;\n case \"direct-overwrite\":\n try {\n writeFileSync(destSkillMd, officialContent);\n writeFileSync(baseSnapshotPath, officialContent);\n manifest.markSynced(skillName, officialHash, officialHash, officialVersion);\n log.info({ skill: skillName, version: officialVersion }, \"upgraded built-in skill\");\n } catch (err) {\n log.warn({ skill: skillName, err }, \"failed to overwrite skill\");\n }\n break;\n case \"keep-user\":\n log.debug({ skill: skillName }, \"keeping user-modified skill\");\n break;\n case \"needs-merge\": {\n // ๅฟ…้กป่ฆๆœ‰ .base.md ๆ‰่ƒฝๅฎ‰ๅ…จๅœฐๅšไธ‰ๆ–นๅˆๅนถ๏ผ›่‹ฅไธๅญ˜ๅœจ๏ผˆๆ—ง็‰ˆๆœฌๆœชๅ†™๏ผ‰๏ผŒ\n // ๅˆ™ๆ— ๆณ•ๅŒบๅˆ†่ฐๆ”นไบ†ไป€ไนˆ๏ผŒ็›ดๆŽฅๅ†™ .conflict ๅปบ่ฎฎ็”จๆˆทๆ‰‹ๅŠจๅค„็†๏ผŒไฟ็•™็”จๆˆทๅ‰ฏๆœฌใ€‚\n if (!existsSync(baseSnapshotPath)) {\n try {\n writeFileSync(\n destSkillMd + \".conflict\",\n renderConflictFile(skillName, officialContent, [\n {\n section: \"(entire file)\",\n official: officialContent,\n user: userContent,\n },\n ]),\n );\n log.warn(\n { skill: skillName },\n \"missing .base.md snapshot โ€” skipping auto-merge, wrote .conflict advisory\",\n );\n } catch (err) {\n log.warn({ skill: skillName, err }, \"failed to write .conflict advisory\");\n }\n break;\n }\n const baseContent = readFileSync(baseSnapshotPath, \"utf-8\");\n const merged = mergeSkillSections(baseContent, officialContent, userContent);\n if (merged.success && merged.content) {\n try {\n writeFileSync(destSkillMd, merged.content);\n writeFileSync(baseSnapshotPath, officialContent);\n const newCurrentHash = sha256(merged.content);\n manifest.markSynced(skillName, officialHash, newCurrentHash, officialVersion);\n log.info({ skill: skillName }, \"auto-merged skill upgrade\");\n } catch (err) {\n log.warn({ skill: skillName, err }, \"failed to write merged skill\");\n }\n } else {\n // Conflict โ†’ write a .conflict sibling for later notification,\n // leave user copy intact.\n try {\n writeFileSync(\n destSkillMd + \".conflict\",\n renderConflictFile(skillName, officialContent, merged.conflicts ?? []),\n );\n log.warn(\n { skill: skillName, conflicts: merged.conflicts?.length },\n \"skill merge conflict โ€” user version kept, .conflict file written\",\n );\n } catch (err) {\n log.warn({ skill: skillName, err }, \"failed to write .conflict file\");\n }\n }\n break;\n }\n }\n }\n}\n\nfunction renderConflictFile(\n skillName: string,\n officialContent: string,\n conflicts: Array<{ section: string; official: string; user: string }>,\n): string {\n const lines = [\n `# Skill upgrade conflict: ${skillName}`,\n ``,\n `The official skill was updated, and your local copy was also modified.`,\n `Please review each section below and reconcile manually.`,\n ``,\n `## Conflicted sections`,\n ``,\n ];\n for (const c of conflicts) {\n lines.push(`### ${c.section}`);\n lines.push(\"\");\n lines.push(\"**Official:**\");\n lines.push(\"```\");\n lines.push(c.official);\n lines.push(\"```\");\n lines.push(\"\");\n lines.push(\"**Your version:**\");\n lines.push(\"```\");\n lines.push(c.user);\n lines.push(\"```\");\n lines.push(\"\");\n }\n lines.push(\"## Full official content\");\n lines.push(\"```\");\n lines.push(officialContent);\n lines.push(\"```\");\n return lines.join(\"\\n\");\n}\n\n/** Create ~/.clawnet/.claude/skills/ if it doesn't exist. */\nfunction ensureSkillsDir(): void {\n if (!existsSync(SKILLS_DIR)) {\n mkdirSync(SKILLS_DIR, { recursive: true });\n log.info({ dir: SKILLS_DIR }, \"created skills directory\");\n }\n}\n\nexport interface SkillInfo {\n name: string;\n description: string;\n}\n\n/** Cached skill list, populated by scanSkills(). */\nlet cachedSkills: SkillInfo[] = [];\n\n/** Scan ~/.clawnet/.claude/skills/ and parse SKILL.md frontmatter\n * to build a list of { name, description }.\n */\nexport function scanSkills(): SkillInfo[] {\n if (!existsSync(SKILLS_DIR)) return [];\n\n let dirs: string[];\n try {\n dirs = readdirSync(SKILLS_DIR, { withFileTypes: true })\n .filter((d) => d.isDirectory())\n .map((d) => d.name);\n } catch {\n log.warn(\"failed to read skills directory for scanning\");\n return [];\n }\n\n const skills: SkillInfo[] = [];\n for (const dirName of dirs) {\n const skillMd = join(SKILLS_DIR, dirName, \"SKILL.md\");\n if (!existsSync(skillMd)) continue;\n\n try {\n const content = readFileSync(skillMd, \"utf-8\");\n const parsed = parseFrontmatter(content);\n if (parsed.name) {\n skills.push({\n name: parsed.name,\n description: parsed.description || dirName,\n });\n }\n } catch (err) {\n log.debug({ skill: dirName, err }, \"failed to parse SKILL.md frontmatter\");\n }\n }\n\n cachedSkills = skills;\n log.info({ count: skills.length }, \"scanned skills\");\n return skills;\n}\n\n/** Get the cached skill list (call scanSkills() first). */\nexport function getSkillList(): SkillInfo[] {\n return cachedSkills;\n}\n\nexport interface PendingNotification {\n count: number;\n text: string;\n}\n\n/**\n * Read pending Skill evolution proposals and render a short notification.\n * Returns null if there are no pending proposals or the file is unreadable.\n */\nexport function getPendingNotification(): PendingNotification | null {\n const pendingPath = join(CLAWNET_DIR, \".claude\", \"pending-evolutions.json\");\n if (!existsSync(pendingPath)) return null;\n try {\n const raw = JSON.parse(readFileSync(pendingPath, \"utf-8\"));\n const pending = Array.isArray(raw?.pending) ? raw.pending : [];\n if (pending.length === 0) return null;\n const lines = pending.map(\n (p: { signal?: string; skillName?: string; problem?: string; confidence?: number }) =>\n `- [${p.signal ?? \"?\"}] ${p.skillName ?? \"?\"}: ${p.problem ?? \"\"} (confidence: ${p.confidence ?? \"?\"})`,\n );\n const text =\n `ๆœ‰ ${pending.length} ๆก Skill ่ฟ›ๅŒ–ๆๆกˆๅพ…ๅฎกๆ ธ๏ผš\\n${lines.join(\"\\n\")}\\n` +\n `ไฝฟ็”จ skill_pending_list ๆŸฅ็œ‹่ฏฆๆƒ…๏ผŒskill_pending_approve / skill_pending_reject ๅค„็†ใ€‚`;\n return { count: pending.length, text };\n } catch (err) {\n log.debug({ err }, \"failed to read pending-evolutions.json\");\n return null;\n }\n}\n\n/** Parse YAML frontmatter from SKILL.md content. */\nfunction parseFrontmatter(content: string): { name: string; description: string } {\n const match = content.match(/^---\\s*\\n([\\s\\S]*?)\\n---/);\n if (!match) return { name: \"\", description: \"\" };\n\n const yaml = match[1];\n const nameMatch = yaml.match(/^name:\\s*(.+)$/m);\n const descMatch = yaml.match(/^description:\\s*(.+)$/m);\n const strip = (s: string) => s.trim().replace(/^[\"']|[\"']$/g, \"\");\n return {\n name: strip(nameMatch?.[1] ?? \"\"),\n description: strip(descMatch?.[1] ?? \"\"),\n };\n}\n\n/** Generate ~/.clawnet/mcp.json with default memory MCP config if it doesn't exist. */\nfunction ensureMcpConfig(): void {\n if (existsSync(MCP_CONFIG_PATH)) {\n log.debug(\"mcp.json already exists, skipping\");\n return;\n }\n\n // Resolve the unified MCP server.js path from the installed package\n let mcpServerPath: string;\n try {\n const req = createRequire(import.meta.url);\n const mcpPkgDir = dirname(req.resolve(\"@mclawnet/mcp-server/package.json\"));\n mcpServerPath = join(mcpPkgDir, \"dist\", \"server.js\");\n } catch {\n log.warn(\"could not resolve @mclawnet/mcp-server package path, skipping mcp.json generation\");\n return;\n }\n\n const config = {\n mcpServers: {\n \"clawnet-mcp\": {\n command: \"node\",\n args: [mcpServerPath],\n },\n },\n };\n\n try {\n // Ensure ~/.clawnet/ exists\n mkdirSync(CLAWNET_DIR, { recursive: true });\n writeFileSync(MCP_CONFIG_PATH, JSON.stringify(config, null, 2) + \"\\n\");\n log.info({ path: MCP_CONFIG_PATH }, \"generated default mcp.json\");\n } catch (err) {\n log.warn({ err }, \"failed to generate mcp.json\");\n }\n}\n","import { existsSync, readFileSync, readdirSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { createLogger } from \"@mclawnet/logger\";\nimport type { AgentGenericRequest } from \"@mclawnet/shared\";\nimport type { HubConnection } from \"./hub-connection.js\";\n\nconst log = createLogger({ module: \"brain-bridge\" });\n\nexport type BrainSetupStatus = \"not_installed\" | \"needs_config\" | \"ready\";\n\nexport interface BrainBridgeOptions {\n brainHomePath?: string;\n brainCorePath?: string;\n}\n\nexport class BrainBridge {\n private brainHome: string;\n private brainCorePath: string;\n\n constructor(\n private hub: HubConnection,\n options?: BrainBridgeOptions\n ) {\n const home = process.env.HOME || process.env.USERPROFILE || \"\";\n this.brainHome =\n options?.brainHomePath ||\n process.env.BRAIN_HOME ||\n join(home, \"BrainData\");\n this.brainCorePath =\n options?.brainCorePath || join(home, \".brain\", \"BrainCore\");\n\n this.hub.registerNamespace(\"brain\", (msg) => this.handleRequest(msg));\n log.info(\n { brainHome: this.brainHome, brainCorePath: this.brainCorePath },\n \"BrainBridge initialized\"\n );\n }\n\n async handleRequest(\n msg: AgentGenericRequest\n ): Promise<Record<string, unknown>> {\n log.info({ action: msg.action, requestId: msg.requestId }, \"brain request\");\n switch (msg.action) {\n case \"setup_status\": {\n const status = this.checkSetup();\n log.info({ status }, \"setup_status result\");\n return { status };\n }\n case \"get_briefing\":\n return await this.getBriefing(msg.params.date as string | undefined);\n case \"get_meeting_recap\":\n return await this.getMeetingRecap(msg.params.recapPath as string);\n default:\n log.warn({ action: msg.action }, \"unknown brain action\");\n throw new Error(`Unknown brain action: ${msg.action}`);\n }\n }\n\n checkSetup(): BrainSetupStatus {\n if (!existsSync(this.brainCorePath)) {\n return \"not_installed\";\n }\n const home = process.env.HOME || process.env.USERPROFILE || \"\";\n const installJson = join(home, \".brain\", \"install.json\");\n if (!existsSync(installJson)) {\n return \"needs_config\";\n }\n if (!existsSync(this.brainHome)) {\n return \"needs_config\";\n }\n return \"ready\";\n }\n\n /** Read the most recent daily briefing report */\n private async getBriefing(\n date?: string\n ): Promise<Record<string, unknown>> {\n const targetDate = date || new Date().toISOString().slice(0, 10);\n const reportsDir = join(this.brainHome, \"reports\", \"daily\");\n\n if (!existsSync(reportsDir)) {\n log.info({ reportsDir }, \"get_briefing: reports dir not found\");\n return { briefing: null, actions: [], projects: [], meetings: [], feed: [] };\n }\n\n const files = readdirSync(reportsDir)\n .filter((f: string) => f.includes(targetDate) && f.endsWith(\".md\"))\n .sort()\n .reverse();\n\n if (files.length === 0) {\n log.info({ targetDate }, \"get_briefing: no report for date\");\n return { briefing: null, actions: [], projects: [], meetings: [], feed: [] };\n }\n\n log.info({ targetDate, file: files[0] }, \"get_briefing: reading report\");\n\n const content = readFileSync(join(reportsDir, files[0]), \"utf-8\");\n\n // Extract TL;DR\n const tldrMatch = content.match(/## TL;DR\\n([\\s\\S]*?)(?=\\n---|\\n## )/);\n const tldr = tldrMatch ? tldrMatch[1].trim() : content.slice(0, 200);\n\n const actions = this.parseActions(content);\n const projects = this.parseProjects(content);\n const meetings = this.parseMeetings(content);\n const feed = this.parseFeed(content);\n\n log.info(\n { actions: actions.length, projects: projects.length, meetings: meetings.length, feed: feed.length },\n \"get_briefing: parsed\"\n );\n\n return {\n briefing: {\n date: targetDate,\n tldr,\n generatedAt: new Date().toISOString(),\n },\n actions,\n projects,\n meetings,\n feed,\n };\n }\n\n /** Parse \"## Action Required\" section into ActionItem[] */\n private parseActions(content: string): Array<Record<string, unknown>> {\n const sectionMatch = content.match(/## Action Required\\n([\\s\\S]*?)(?=\\n---|\\n## [^A])/);\n if (!sectionMatch) return [];\n\n const section = sectionMatch[1];\n const items: Array<Record<string, unknown>> = [];\n let currentPriority: string = \"p3\";\n let idCounter = 0;\n\n for (const line of section.split(\"\\n\")) {\n // Detect priority headers\n if (line.includes(\"๐Ÿ”ด Today\")) { currentPriority = \"p1\"; continue; }\n if (line.includes(\"๐ŸŸก This Week\")) { currentPriority = \"p2\"; continue; }\n if (line.includes(\"โšช FYI\") || line.includes(\"FYI โ€”\")) { currentPriority = \"p4\"; continue; }\n\n // Numbered items: \"1. **Title** โ†’ description\"\n const numberedMatch = line.match(/^\\d+\\.\\s+\\*\\*(.+?)\\*\\*\\s*[โ†’โ€”โ€“-]\\s*(.+)/);\n if (numberedMatch) {\n items.push({\n id: `action-${++idCounter}`,\n priority: currentPriority,\n title: `${numberedMatch[1].trim()} โ€” ${numberedMatch[2].trim()}`,\n source: this.guessSource(numberedMatch[2]),\n timeAgo: \"\",\n done: false,\n });\n continue;\n }\n\n // Bullet items under FYI: \"- description\"\n if (currentPriority === \"p4\") {\n const bulletMatch = line.match(/^-\\s+(.+)/);\n if (bulletMatch) {\n items.push({\n id: `action-${++idCounter}`,\n priority: \"p4\",\n title: bulletMatch[1].replace(/\\*\\*/g, \"\").trim(),\n source: this.guessSource(bulletMatch[1]),\n timeAgo: \"\",\n done: false,\n });\n }\n }\n }\n\n return items;\n }\n\n /** Parse project sections \"## ๐Ÿ”ต ProjectName\" with Status tables */\n private parseProjects(content: string): Array<Record<string, unknown>> {\n const projects: Array<Record<string, unknown>> = [];\n // Match \"## ๐Ÿ”ต ProjectName\" sections\n const projectRegex = /## ๐Ÿ”ต\\s+(.+)\\n([\\s\\S]*?)(?=\\n## |$)/g;\n let match;\n\n while ((match = projectRegex.exec(content)) !== null) {\n const name = match[1].trim();\n const body = match[2];\n\n // Parse status table: | ๐ŸŸก At Risk | ... | or | ๐ŸŸข On Track | ... |\n let status: string = \"on_track\";\n const statusMatch = body.match(/\\|\\s*(๐ŸŸก|๐Ÿ”ด|๐ŸŸข)\\s*(.*?)\\s*\\|/);\n if (statusMatch) {\n const icon = statusMatch[1];\n if (icon === \"๐Ÿ”ด\") status = \"blocked\";\n else if (icon === \"๐ŸŸก\") status = \"blocked\";\n else if (icon === \"๐ŸŸข\") status = \"good\";\n }\n\n // Count \"Teams Chats\" subsections (#### headers under ### Teams Chats)\n const teamsSection = body.match(/### Teams Chats\\n([\\s\\S]*?)(?=\\n### [^T]|\\n---|\\n## |$)/);\n let newMessages = 0;\n if (teamsSection) {\n const chatHeaders = teamsSection[1].match(/^####/gm);\n newMessages = chatHeaders ? chatHeaders.length : 0;\n }\n\n // Count \"Key Decisions\" items\n let pendingDecisions = 0;\n const decisionsMatches = body.match(/\\*\\*\\[(?:Decided|Leaning)\\]\\*\\*/g);\n if (decisionsMatches) pendingDecisions = decisionsMatches.length;\n\n projects.push({\n slug: name.toLowerCase().replace(/[^a-z0-9]+/g, \"-\"),\n name,\n status,\n newMessages,\n pendingDecisions,\n });\n }\n\n return projects;\n }\n\n /** Parse meetings from \"### Meetings\" subsections */\n private parseMeetings(content: string): Array<Record<string, unknown>> {\n const meetings: Array<Record<string, unknown>> = [];\n // Find all \"#### MeetingTitle\" under \"### Meetings\" sections\n const meetingSectionRegex = /### Meetings\\n([\\s\\S]*?)(?=\\n### [^M]|\\n---|\\n## |$)/g;\n let sectionMatch;\n let idCounter = 0;\n\n while ((sectionMatch = meetingSectionRegex.exec(content)) !== null) {\n const section = sectionMatch[1];\n // Each meeting: \"#### Title\\n\\n๐Ÿ“… time | status | participants | host\"\n const meetingRegex = /####\\s+(.+)\\n\\n๐Ÿ“…\\s*(\\S+)\\s+\\w+\\s*\\|\\s*(\\w+)/g;\n let m;\n\n while ((m = meetingRegex.exec(section)) !== null) {\n const title = m[1].trim();\n const time = m[2].trim();\n const statusWord = m[3].toLowerCase();\n\n let status = \"completed\";\n if (statusWord === \"missed\") status = \"completed\"; // still show recap\n else if (statusWord === \"upcoming\") status = \"upcoming\";\n else if (statusWord.includes(\"progress\")) status = \"in_progress\";\n\n // Get the text slice for this specific meeting (from current match to next #### or section end)\n const meetingEndIdx = section.indexOf(\"\\n####\", m.index + m[0].length);\n const meetingSlice = meetingEndIdx !== -1\n ? section.slice(m.index, meetingEndIdx)\n : section.slice(m.index);\n\n const recapMatch = meetingSlice.match(/๐Ÿ“Ž\\s*\\[Full recap\\]\\((.+?)\\)/);\n const recapPath = recapMatch ? recapMatch[1] : undefined;\n\n meetings.push({\n id: `meeting-${++idCounter}`,\n time,\n title,\n status,\n hasRecap: !!recapPath,\n recapPath,\n });\n }\n }\n\n return meetings;\n }\n\n /** Parse feed items from Teams Chats subsections across all project sections and Announcements */\n private parseFeed(content: string): Array<Record<string, unknown>> {\n const items: Array<Record<string, unknown>> = [];\n let idCounter = 0;\n\n // 1) Extract feed items from \"### Teams Chats\" under \"## ๐Ÿ”ต ProjectName\" sections\n const projectRegex = /## ๐Ÿ”ต\\s+(.+)\\n([\\s\\S]*?)(?=\\n## |$)/g;\n let projectMatch;\n\n while ((projectMatch = projectRegex.exec(content)) !== null) {\n const projectName = projectMatch[1].trim();\n const projectBody = projectMatch[2];\n\n this.extractTeamsChatItems(projectBody, projectName, items, idCounter);\n idCounter = items.length;\n }\n\n // 2) Extract feed items from \"## ๐Ÿ“ข Announcements & FYI\" section (no project)\n const announcementMatch = content.match(/## ๐Ÿ“ข\\s+Announcements[^\\n]*\\n([\\s\\S]*?)(?=\\n## |$)/);\n if (announcementMatch) {\n this.extractTeamsChatItems(announcementMatch[1], \"\", items, idCounter);\n }\n\n return items;\n }\n\n /** Extract chat items from a \"### Teams Chats\" subsection within a body block */\n private extractTeamsChatItems(\n body: string,\n project: string,\n items: Array<Record<string, unknown>>,\n _startId: number\n ): void {\n // Find \"### Teams Chats\" subsection\n const teamsChatMatch = body.match(/### Teams Chats\\n([\\s\\S]*?)(?=\\n### [^T]|\\n---|\\n## |$)/);\n if (!teamsChatMatch) return;\n\n const teamsSection = teamsChatMatch[1];\n\n // Find \"#### ChatTitle โ€” Priority\" headers and their content\n const chatRegex = /####\\s+(.+?)(?:\\s*โ€”\\s*(.+))?\\n([\\s\\S]*?)(?=\\n####|\\n###|\\n---|$)/g;\n let chatMatch;\n\n while ((chatMatch = chatRegex.exec(teamsSection)) !== null) {\n const chatBody = chatMatch[3];\n\n // Extract bold names like **Person Name** as sender\n const senderMatch = chatBody.match(/\\*\\*(.+?)\\*\\*/);\n const sender = senderMatch ? senderMatch[1].trim() : \"Unknown\";\n\n // Extract content: first meaningful line after the sender, or first sentence\n let contentPreview = \"\";\n const lines = chatBody.split(\"\\n\").filter((l: string) => l.trim().length > 0);\n for (const line of lines) {\n // Skip lines that are just metadata (timestamps, status indicators)\n const cleaned = line.replace(/\\*\\*.*?\\*\\*/g, \"\").replace(/[>*-]/g, \"\").trim();\n if (cleaned.length > 10) {\n contentPreview = cleaned.slice(0, 100);\n break;\n }\n }\n // Fallback: use the entire chat body trimmed\n if (!contentPreview && lines.length > 0) {\n contentPreview = lines[0].replace(/\\*\\*/g, \"\").trim().slice(0, 100);\n }\n\n // Try to extract a time from the body (e.g., \"10:30\" or \"14:23\")\n const timeMatch = chatBody.match(/(\\d{1,2}:\\d{2})/);\n const time = timeMatch ? timeMatch[1] : \"\";\n\n items.push({\n id: `feed-${items.length + 1}`,\n time,\n source: \"teams\",\n sender,\n content: contentPreview,\n project: project || undefined,\n });\n }\n }\n\n /** Fetch and parse a meeting recap file */\n private async getMeetingRecap(recapPath: string): Promise<Record<string, unknown>> {\n if (!recapPath) {\n return { error: \"No recap path provided\" };\n }\n const fullPath = join(this.brainHome, recapPath);\n if (!existsSync(fullPath)) {\n log.warn({ fullPath }, \"meeting recap file not found\");\n return { error: \"Recap file not found\" };\n }\n const content = readFileSync(fullPath, \"utf-8\");\n return { recap: this.parseRecapMarkdown(content) };\n }\n\n /** Parse meeting recap markdown into structured sections */\n private parseRecapMarkdown(content: string): Record<string, unknown> {\n // Extract TL;DR / Summary section\n const tldrMatch = content.match(/##\\s*(?:TL;DR|Summary|ๆฆ‚่ฆ)\\n([\\s\\S]*?)(?=\\n## |\\n---|\\n$)/);\n const tldr = tldrMatch ? tldrMatch[1].trim() : \"\";\n\n // Extract \"Relevant to You\" / \"ไธŽไฝ ็›ธๅ…ณ\" section\n const relevantMatch = content.match(/##\\s*(?:ไธŽไฝ ็›ธๅ…ณ|Relevant|For You|Action for You)\\n([\\s\\S]*?)(?=\\n## |\\n---|\\n$)/);\n const relevant = relevantMatch ? relevantMatch[1].trim() : \"\";\n\n // Extract \"Decisions\" / \"ๅ†ณๅฎšไบ‹้กน\" / \"Key Decisions\" section\n const decisionsMatch = content.match(/##\\s*(?:ๅ†ณๅฎšไบ‹้กน|Decisions|Key Decisions)\\n([\\s\\S]*?)(?=\\n## |\\n---|\\n$)/);\n const decisions = decisionsMatch ? decisionsMatch[1].trim() : \"\";\n\n // Extract \"Action Items\" / \"่กŒๅŠจ้กน\" section\n const actionsMatch = content.match(/##\\s*(?:่กŒๅŠจ้กน|Action Items|Next Steps)\\n([\\s\\S]*?)(?=\\n## |\\n---|\\n$)/);\n const actionItems = actionsMatch ? actionsMatch[1].trim() : \"\";\n\n return {\n tldr,\n relevant,\n decisions,\n actionItems,\n rawMarkdown: content,\n };\n }\n\n /** Guess message source from text content */\n private guessSource(text: string): string {\n const lower = text.toLowerCase();\n if (lower.includes(\"teams\")) return \"teams\";\n if (lower.includes(\"email\") || lower.includes(\"mail\")) return \"email\";\n if (lower.includes(\"meeting\") || lower.includes(\"sync\")) return \"meeting\";\n if (lower.includes(\"pr\") || lower.includes(\"ado\") || lower.includes(\"work item\")) return \"ado\";\n return \"teams\";\n }\n}\n","import { existsSync, readFileSync, statSync } from \"node:fs\";\nimport { extname, isAbsolute } from \"node:path\";\nimport { createLogger } from \"@mclawnet/logger\";\nimport type { AgentGenericRequest } from \"@mclawnet/shared\";\nimport type { HubConnection } from \"./hub-connection.js\";\n\nconst log = createLogger({ module: \"fs-bridge\" });\n\nconst MAX_TEXT_SIZE = 5 * 1024 * 1024; // 5MB\n\nconst MIME_MAP: Record<string, string> = {\n \".ts\": \"text/typescript\", \".tsx\": \"text/typescript\",\n \".js\": \"text/javascript\", \".jsx\": \"text/javascript\",\n \".json\": \"application/json\", \".html\": \"text/html\",\n \".css\": \"text/css\", \".md\": \"text/markdown\",\n \".py\": \"text/x-python\", \".sh\": \"text/x-shellscript\",\n \".yaml\": \"text/yaml\", \".yml\": \"text/yaml\",\n \".xml\": \"text/xml\", \".sql\": \"text/x-sql\",\n \".svg\": \"image/svg+xml\",\n \".png\": \"image/png\", \".jpg\": \"image/jpeg\", \".jpeg\": \"image/jpeg\",\n \".gif\": \"image/gif\", \".webp\": \"image/webp\",\n \".mp4\": \"video/mp4\", \".webm\": \"video/webm\",\n \".mp3\": \"audio/mpeg\", \".wav\": \"audio/wav\",\n};\n\nfunction getMimeType(filePath: string): string {\n return MIME_MAP[extname(filePath).toLowerCase()] || \"application/octet-stream\";\n}\n\nfunction isTextMime(mime: string): boolean {\n return mime.startsWith(\"text/\") || mime === \"application/json\" || mime === \"image/svg+xml\";\n}\n\nexport class FsBridge {\n constructor(private hub: HubConnection) {\n this.hub.registerNamespace(\"fs\", (msg) => this.handleRequest(msg));\n log.info(\"FsBridge initialized\");\n }\n\n async handleRequest(msg: AgentGenericRequest): Promise<Record<string, unknown>> {\n log.info({ action: msg.action, requestId: msg.requestId }, \"fs request\");\n switch (msg.action) {\n case \"read\":\n return this.readFile(msg.params);\n default:\n throw new Error(`Unknown fs action: ${msg.action}`);\n }\n }\n\n private readFile(params: Record<string, unknown>): Record<string, unknown> {\n const filePath = params.path as string;\n if (!filePath) throw new Error(\"Missing path parameter\");\n\n // Security: only allow absolute paths (no relative traversal tricks)\n if (!isAbsolute(filePath)) {\n throw new Error(`Access denied: only absolute paths allowed`);\n }\n\n if (!existsSync(filePath)) {\n throw new Error(`File not found: ${filePath}`);\n }\n\n const stat = statSync(filePath);\n if (!stat.isFile()) {\n throw new Error(`Not a file: ${filePath}`);\n }\n\n const mimeType = getMimeType(filePath);\n const totalSize = stat.size;\n\n if (isTextMime(mimeType)) {\n const raw = readFileSync(filePath, \"utf-8\");\n const truncated = raw.length > MAX_TEXT_SIZE;\n const content = truncated ? raw.slice(0, MAX_TEXT_SIZE) : raw;\n return { content, encoding: \"utf-8\", size: content.length, totalSize, mimeType, truncated };\n }\n\n // Binary: base64\n const buf = readFileSync(filePath);\n const truncated = buf.length > MAX_TEXT_SIZE;\n const slice = truncated ? buf.subarray(0, MAX_TEXT_SIZE) : buf;\n return { content: slice.toString(\"base64\"), encoding: \"base64\", size: slice.length, totalSize, mimeType, truncated };\n }\n}\n"],"mappings":"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","names":["homedir","join","createLogger","previewFields","existsSync","readdirSync","readFileSync","join","homedir","createLogger","log","log","createLogger","process","previewFields","existsSync","readFileSync","readdirSync","join","createLogger","log","existsSync","readFileSync","statSync","createLogger","log","stat","truncated","createLogger","log","join","homedir"]}