agentmesh-ai 0.1.0

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 (123) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +247 -0
  3. package/dist/cli/commands/init.d.ts +2 -0
  4. package/dist/cli/commands/init.d.ts.map +1 -0
  5. package/dist/cli/commands/init.js +134 -0
  6. package/dist/cli/commands/init.js.map +1 -0
  7. package/dist/cli/commands/memory.d.ts +8 -0
  8. package/dist/cli/commands/memory.d.ts.map +1 -0
  9. package/dist/cli/commands/memory.js +40 -0
  10. package/dist/cli/commands/memory.js.map +1 -0
  11. package/dist/cli/commands/serve.d.ts +8 -0
  12. package/dist/cli/commands/serve.d.ts.map +1 -0
  13. package/dist/cli/commands/serve.js +90 -0
  14. package/dist/cli/commands/serve.js.map +1 -0
  15. package/dist/cli/commands/setup.d.ts +2 -0
  16. package/dist/cli/commands/setup.d.ts.map +1 -0
  17. package/dist/cli/commands/setup.js +117 -0
  18. package/dist/cli/commands/setup.js.map +1 -0
  19. package/dist/cli/commands/status.d.ts +2 -0
  20. package/dist/cli/commands/status.d.ts.map +1 -0
  21. package/dist/cli/commands/status.js +66 -0
  22. package/dist/cli/commands/status.js.map +1 -0
  23. package/dist/cli/index.d.ts +3 -0
  24. package/dist/cli/index.d.ts.map +1 -0
  25. package/dist/cli/index.js +50 -0
  26. package/dist/cli/index.js.map +1 -0
  27. package/dist/conversation/client.d.ts +72 -0
  28. package/dist/conversation/client.d.ts.map +1 -0
  29. package/dist/conversation/client.js +245 -0
  30. package/dist/conversation/client.js.map +1 -0
  31. package/dist/conversation/index.d.ts +7 -0
  32. package/dist/conversation/index.d.ts.map +1 -0
  33. package/dist/conversation/index.js +4 -0
  34. package/dist/conversation/index.js.map +1 -0
  35. package/dist/conversation/protocol.d.ts +217 -0
  36. package/dist/conversation/protocol.d.ts.map +1 -0
  37. package/dist/conversation/protocol.js +7 -0
  38. package/dist/conversation/protocol.js.map +1 -0
  39. package/dist/conversation/recorder.d.ts +4 -0
  40. package/dist/conversation/recorder.d.ts.map +1 -0
  41. package/dist/conversation/recorder.js +60 -0
  42. package/dist/conversation/recorder.js.map +1 -0
  43. package/dist/conversation/server.d.ts +59 -0
  44. package/dist/conversation/server.d.ts.map +1 -0
  45. package/dist/conversation/server.js +529 -0
  46. package/dist/conversation/server.js.map +1 -0
  47. package/dist/index.d.ts +3 -0
  48. package/dist/index.d.ts.map +1 -0
  49. package/dist/index.js +3 -0
  50. package/dist/index.js.map +1 -0
  51. package/dist/integrations/claude-md.d.ts +2 -0
  52. package/dist/integrations/claude-md.d.ts.map +1 -0
  53. package/dist/integrations/claude-md.js +35 -0
  54. package/dist/integrations/claude-md.js.map +1 -0
  55. package/dist/integrations/copilot.d.ts +2 -0
  56. package/dist/integrations/copilot.d.ts.map +1 -0
  57. package/dist/integrations/copilot.js +39 -0
  58. package/dist/integrations/copilot.js.map +1 -0
  59. package/dist/integrations/detect.d.ts +9 -0
  60. package/dist/integrations/detect.d.ts.map +1 -0
  61. package/dist/integrations/detect.js +34 -0
  62. package/dist/integrations/detect.js.map +1 -0
  63. package/dist/mcp/conversation-tools.d.ts +4 -0
  64. package/dist/mcp/conversation-tools.d.ts.map +1 -0
  65. package/dist/mcp/conversation-tools.js +540 -0
  66. package/dist/mcp/conversation-tools.js.map +1 -0
  67. package/dist/mcp/index.d.ts +3 -0
  68. package/dist/mcp/index.d.ts.map +1 -0
  69. package/dist/mcp/index.js +86 -0
  70. package/dist/mcp/index.js.map +1 -0
  71. package/dist/mcp/memory-tools.d.ts +4 -0
  72. package/dist/mcp/memory-tools.d.ts.map +1 -0
  73. package/dist/mcp/memory-tools.js +195 -0
  74. package/dist/mcp/memory-tools.js.map +1 -0
  75. package/dist/mcp/resources.d.ts +3 -0
  76. package/dist/mcp/resources.d.ts.map +1 -0
  77. package/dist/mcp/resources.js +23 -0
  78. package/dist/mcp/resources.js.map +1 -0
  79. package/dist/memory/index.d.ts +7 -0
  80. package/dist/memory/index.d.ts.map +1 -0
  81. package/dist/memory/index.js +6 -0
  82. package/dist/memory/index.js.map +1 -0
  83. package/dist/memory/merge-view.d.ts +9 -0
  84. package/dist/memory/merge-view.d.ts.map +1 -0
  85. package/dist/memory/merge-view.js +88 -0
  86. package/dist/memory/merge-view.js.map +1 -0
  87. package/dist/memory/reader.d.ts +8 -0
  88. package/dist/memory/reader.d.ts.map +1 -0
  89. package/dist/memory/reader.js +53 -0
  90. package/dist/memory/reader.js.map +1 -0
  91. package/dist/memory/schema.d.ts +154 -0
  92. package/dist/memory/schema.d.ts.map +1 -0
  93. package/dist/memory/schema.js +34 -0
  94. package/dist/memory/schema.js.map +1 -0
  95. package/dist/memory/searcher.d.ts +7 -0
  96. package/dist/memory/searcher.d.ts.map +1 -0
  97. package/dist/memory/searcher.js +49 -0
  98. package/dist/memory/searcher.js.map +1 -0
  99. package/dist/memory/secret-scanner.d.ts +21 -0
  100. package/dist/memory/secret-scanner.d.ts.map +1 -0
  101. package/dist/memory/secret-scanner.js +54 -0
  102. package/dist/memory/secret-scanner.js.map +1 -0
  103. package/dist/memory/types.d.ts +71 -0
  104. package/dist/memory/types.d.ts.map +1 -0
  105. package/dist/memory/types.js +5 -0
  106. package/dist/memory/types.js.map +1 -0
  107. package/dist/memory/writer.d.ts +4 -0
  108. package/dist/memory/writer.d.ts.map +1 -0
  109. package/dist/memory/writer.js +114 -0
  110. package/dist/memory/writer.js.map +1 -0
  111. package/dist/utils/git.d.ts +7 -0
  112. package/dist/utils/git.d.ts.map +1 -0
  113. package/dist/utils/git.js +46 -0
  114. package/dist/utils/git.js.map +1 -0
  115. package/dist/utils/id.d.ts +6 -0
  116. package/dist/utils/id.d.ts.map +1 -0
  117. package/dist/utils/id.js +20 -0
  118. package/dist/utils/id.js.map +1 -0
  119. package/dist/utils/yaml.d.ts +7 -0
  120. package/dist/utils/yaml.d.ts.map +1 -0
  121. package/dist/utils/yaml.js +50 -0
  122. package/dist/utils/yaml.js.map +1 -0
  123. package/package.json +59 -0
@@ -0,0 +1,86 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * AgentHub MCP Server entry point.
4
+ *
5
+ * This runs as a stdio MCP server, exposing shared memory tools
6
+ * to AI coding tools like Claude Code and Cursor.
7
+ */
8
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
9
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
10
+ import { registerMemoryTools } from './memory-tools.js';
11
+ import { registerConversationTools } from './conversation-tools.js';
12
+ import { registerResources } from './resources.js';
13
+ import { findAgentHubDir } from '../utils/git.js';
14
+ import { ConversationClient } from '../conversation/client.js';
15
+ import { readHubConfig } from '../memory/reader.js';
16
+ async function main() {
17
+ const server = new McpServer({
18
+ name: 'AgentHub',
19
+ version: '0.1.0',
20
+ });
21
+ // Resolve .agenthub directory from current working directory
22
+ const cwd = process.cwd();
23
+ let agentHubDir = findAgentHubDir(cwd);
24
+ // Read agent identity from environment variables (set during setup)
25
+ const agentId = process.env.AGENTHUB_AGENT_ID ?? 'default-agent';
26
+ const getDir = () => {
27
+ if (!agentHubDir) {
28
+ // Try again in case it was created after MCP started
29
+ agentHubDir = findAgentHubDir(cwd);
30
+ if (!agentHubDir) {
31
+ throw new Error('No .agenthub/ directory found. Run "npx agenthub init" first.');
32
+ }
33
+ }
34
+ return agentHubDir;
35
+ };
36
+ const getAgentId = () => agentId;
37
+ // Try to connect to conversation space if available
38
+ let conversationClient = null;
39
+ const serverUrl = process.env.AGENTHUB_SERVER_URL;
40
+ if (serverUrl) {
41
+ try {
42
+ const hub = await readHubConfig(getDir());
43
+ const agentInfo = hub?.agents.find(a => a.id === agentId);
44
+ conversationClient = new ConversationClient({
45
+ url: serverUrl,
46
+ agent: {
47
+ id: agentId,
48
+ displayName: agentInfo?.display_name ?? agentId,
49
+ role: agentInfo?.role ?? 'developer',
50
+ tool: agentInfo?.tool ?? 'unknown',
51
+ },
52
+ key: process.env.AGENTHUB_SERVER_KEY,
53
+ });
54
+ await conversationClient.connect();
55
+ // Auto-sync local memory to conversation space
56
+ try {
57
+ const { readAgentMemory } = await import('../memory/reader.js');
58
+ const { join } = await import('node:path');
59
+ const myMemory = await readAgentMemory(join(getDir(), 'memory', `${agentId}.yaml`));
60
+ if (myMemory && myMemory.entries.length > 0) {
61
+ conversationClient.syncMemory(myMemory.entries);
62
+ }
63
+ }
64
+ catch {
65
+ // Memory sync is best-effort
66
+ }
67
+ }
68
+ catch {
69
+ // Conversation space not available — memory tools still work fine
70
+ conversationClient = null;
71
+ }
72
+ }
73
+ const getClient = () => conversationClient;
74
+ // Register tools and resources
75
+ registerMemoryTools(server, getDir, getAgentId, getClient);
76
+ registerConversationTools(server, getDir, getAgentId, getClient);
77
+ registerResources(server, getDir);
78
+ // Connect via stdio
79
+ const transport = new StdioServerTransport();
80
+ await server.connect(transport);
81
+ }
82
+ main().catch((err) => {
83
+ console.error('AgentHub MCP server failed to start:', err);
84
+ process.exit(1);
85
+ });
86
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/mcp/index.ts"],"names":[],"mappings":";AACA;;;;;GAKG;AACH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,yBAAyB,EAAE,MAAM,yBAAyB,CAAC;AACpE,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEpD,KAAK,UAAU,IAAI;IACjB,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;QAC3B,IAAI,EAAE,UAAU;QAChB,OAAO,EAAE,OAAO;KACjB,CAAC,CAAC;IAEH,6DAA6D;IAC7D,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAC1B,IAAI,WAAW,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC;IAEvC,oEAAoE;IACpE,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,eAAe,CAAC;IAEjE,MAAM,MAAM,GAAG,GAAG,EAAE;QAClB,IAAI,CAAC,WAAW,EAAE,CAAC;YACjB,qDAAqD;YACrD,WAAW,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC;YACnC,IAAI,CAAC,WAAW,EAAE,CAAC;gBACjB,MAAM,IAAI,KAAK,CACb,+DAA+D,CAChE,CAAC;YACJ,CAAC;QACH,CAAC;QACD,OAAO,WAAW,CAAC;IACrB,CAAC,CAAC;IAEF,MAAM,UAAU,GAAG,GAAG,EAAE,CAAC,OAAO,CAAC;IAEjC,oDAAoD;IACpD,IAAI,kBAAkB,GAA8B,IAAI,CAAC;IACzD,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC;IAElD,IAAI,SAAS,EAAE,CAAC;QACd,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,aAAa,CAAC,MAAM,EAAE,CAAC,CAAC;YAC1C,MAAM,SAAS,GAAG,GAAG,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,OAAO,CAAC,CAAC;YAE1D,kBAAkB,GAAG,IAAI,kBAAkB,CAAC;gBAC1C,GAAG,EAAE,SAAS;gBACd,KAAK,EAAE;oBACL,EAAE,EAAE,OAAO;oBACX,WAAW,EAAE,SAAS,EAAE,YAAY,IAAI,OAAO;oBAC/C,IAAI,EAAE,SAAS,EAAE,IAAI,IAAI,WAAW;oBACpC,IAAI,EAAE,SAAS,EAAE,IAAI,IAAI,SAAS;iBACnC;gBACD,GAAG,EAAE,OAAO,CAAC,GAAG,CAAC,mBAAmB;aACrC,CAAC,CAAC;YAEH,MAAM,kBAAkB,CAAC,OAAO,EAAE,CAAC;YAEnC,+CAA+C;YAC/C,IAAI,CAAC;gBACH,MAAM,EAAE,eAAe,EAAE,GAAG,MAAM,MAAM,CAAC,qBAAqB,CAAC,CAAC;gBAChE,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,CAAC;gBAC3C,MAAM,QAAQ,GAAG,MAAM,eAAe,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,QAAQ,EAAE,GAAG,OAAO,OAAO,CAAC,CAAC,CAAC;gBACpF,IAAI,QAAQ,IAAI,QAAQ,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBAC5C,kBAAkB,CAAC,UAAU,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;gBAClD,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,6BAA6B;YAC/B,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,kEAAkE;YAClE,kBAAkB,GAAG,IAAI,CAAC;QAC5B,CAAC;IACH,CAAC;IAED,MAAM,SAAS,GAAG,GAAG,EAAE,CAAC,kBAAkB,CAAC;IAE3C,+BAA+B;IAC/B,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,CAAC,CAAC;IAC3D,yBAAyB,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,CAAC,CAAC;IACjE,iBAAiB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAElC,oBAAoB;IACpB,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;AAClC,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACnB,OAAO,CAAC,KAAK,CAAC,sCAAsC,EAAE,GAAG,CAAC,CAAC;IAC3D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import type { ConversationClient } from '../conversation/client.js';
3
+ export declare function registerMemoryTools(server: McpServer, getAgentHubDir: () => string, getAgentId: () => string, getClient?: () => ConversationClient | null): void;
4
+ //# sourceMappingURL=memory-tools.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory-tools.d.ts","sourceRoot":"","sources":["../../src/mcp/memory-tools.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAEpE,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,SAAS,EACjB,cAAc,EAAE,MAAM,MAAM,EAC5B,UAAU,EAAE,MAAM,MAAM,EACxB,SAAS,CAAC,EAAE,MAAM,kBAAkB,GAAG,IAAI,QAkO5C"}
@@ -0,0 +1,195 @@
1
+ /**
2
+ * MCP tool definitions for shared memory operations.
3
+ */
4
+ import { z } from 'zod';
5
+ import { readAllAgentMemories, readHubConfig } from '../memory/reader.js';
6
+ import { writeMemoryEntry } from '../memory/writer.js';
7
+ import { searchMemories } from '../memory/searcher.js';
8
+ import { mergeMemories, formatMergedMemories } from '../memory/merge-view.js';
9
+ export function registerMemoryTools(server, getAgentHubDir, getAgentId, getClient) {
10
+ server.tool('read_memory', `Read the project's shared memory — all knowledge recorded by all AI agents working on this project.
11
+
12
+ Call this tool when you start a new task or need to understand the project context.
13
+ It returns everything the team knows: tech stack, APIs, conventions, decisions, gotchas.`, {
14
+ tags: z.array(z.string()).optional().describe('Filter by tags (e.g. ["api", "user-service"])'),
15
+ agent: z.string().optional().describe('Only read one specific agent\'s memory'),
16
+ limit: z.number().optional().describe('Max entries to return (default 50). Use search_memory for targeted lookups.'),
17
+ }, async ({ tags, agent, limit }) => {
18
+ const dir = getAgentHubDir();
19
+ const memories = await readAllAgentMemories(dir);
20
+ // Merge in synced memories from conversation space (may be newer than local Git files)
21
+ const client = getClient?.();
22
+ if (client?.isConnected) {
23
+ for (const synced of client.syncedMemories) {
24
+ const localExists = memories.some(m => m.agent === synced.agent.id);
25
+ if (!localExists) {
26
+ const agentMemory = {
27
+ agent: synced.agent.id,
28
+ role: synced.agent.role,
29
+ tool: synced.agent.tool,
30
+ last_active: new Date().toISOString(),
31
+ entries: synced.entries,
32
+ };
33
+ memories.push(agentMemory);
34
+ // Persist to local disk so it survives server restart
35
+ try {
36
+ const { writeYaml } = await import('../utils/yaml.js');
37
+ const { join } = await import('node:path');
38
+ await writeYaml(join(dir, 'memory', `${synced.agent.id}.yaml`), agentMemory);
39
+ }
40
+ catch {
41
+ // Best-effort persistence
42
+ }
43
+ }
44
+ }
45
+ }
46
+ // mergeMemories without limit to get total count, then with limit
47
+ const allMerged = mergeMemories(memories, { tags, agent });
48
+ const totalCount = allMerged.length;
49
+ const limited = mergeMemories(memories, { tags, agent, limit: limit ?? 50 });
50
+ let text = formatMergedMemories(limited, totalCount);
51
+ // Check for active discussions that need attention
52
+ if (client?.isConnected) {
53
+ const topics = client.topics;
54
+ const myId = getAgentId();
55
+ // Find topics where we haven't spoken yet
56
+ const pendingTopics = [];
57
+ for (const topic of topics) {
58
+ const messages = client.getTopicMessages(topic);
59
+ const iSpoke = messages.some(m => m.from.id === myId);
60
+ if (!iSpoke && messages.length > 0) {
61
+ pendingTopics.push(topic);
62
+ }
63
+ }
64
+ if (pendingTopics.length > 0) {
65
+ text += '\n\n⚠️ ACTIVE DISCUSSIONS WAITING FOR YOUR INPUT:\n';
66
+ for (const topic of pendingTopics) {
67
+ const messages = client.getTopicMessages(topic);
68
+ const lastMsg = messages[messages.length - 1];
69
+ text += ` → "${topic}" — last message from ${lastMsg.from.displayName}: "${lastMsg.content.slice(0, 80)}..."\n`;
70
+ }
71
+ text += '\nUse the discuss tool to join these discussions.\n';
72
+ }
73
+ // Check for pending decisions that need this human's vote
74
+ const pendingDecisions = client.pendingDecisions;
75
+ if (pendingDecisions.length > 0) {
76
+ text += '\n\n🗳️ PENDING DECISIONS REQUIRING YOUR HUMAN\'S VOTE:\n';
77
+ for (const d of pendingDecisions) {
78
+ text += ` → "${d.topic}" — proposed by ${d.proposedBy.displayName}`;
79
+ if (d.recommendation)
80
+ text += ` (recommends: ${d.recommendation})`;
81
+ text += `\n Options: ${d.options.map(o => o.label).join(', ')}`;
82
+ text += `\n Decision ID: ${d.decisionId}\n`;
83
+ }
84
+ text += '\nUse the vote_on_decision tool to ask your human to vote.\n';
85
+ }
86
+ // Check for meetings waiting for this agent
87
+ const meetings = client.meetings;
88
+ const myMeetings = meetings.filter(m => m.status === 'waiting' && m.missingAgents.includes(myId));
89
+ if (myMeetings.length > 0) {
90
+ text += '\n\n📢 MEETINGS WAITING FOR YOU:\n';
91
+ for (const m of myMeetings) {
92
+ text += ` → "${m.topic}" — started by ${m.startedBy}\n`;
93
+ text += ` Present: ${m.presentAgents.join(', ')}\n`;
94
+ text += ` Missing: ${m.missingAgents.join(', ')}\n`;
95
+ }
96
+ text += '\nYou are already connected — the meeting will start automatically.\n';
97
+ }
98
+ const activeMeetings = meetings.filter(m => m.status === 'active');
99
+ if (activeMeetings.length > 0) {
100
+ text += '\n\n🟢 ACTIVE MEETINGS:\n';
101
+ for (const m of activeMeetings) {
102
+ text += ` → "${m.topic}" — all members present. Use discuss tool to participate.\n`;
103
+ }
104
+ }
105
+ }
106
+ return { content: [{ type: 'text', text }] };
107
+ });
108
+ server.tool('write_memory', `Record important project knowledge to shared memory so other AI agents can benefit.
109
+
110
+ WHEN TO USE — record after you:
111
+ ✅ Create or modify API endpoints (paths, params, return types)
112
+ ✅ Define data models (fields, types, constraints)
113
+ ✅ Make a tech decision and why (e.g. chose PostgreSQL for transactions)
114
+ ✅ Discover a gotcha or fix a tricky bug (so others don't repeat it)
115
+ ✅ Use an important dependency or library
116
+ ✅ Establish a convention that affects others (naming, error handling)
117
+ ✅ Complete a significant module or feature
118
+
119
+ WHEN NOT TO USE — don't record:
120
+ ❌ Implementation details visible in the code itself
121
+ ❌ Temporary debug info or experiments
122
+ ❌ Info only relevant to yourself, not the team
123
+ ❌ Things already in README or code comments
124
+
125
+ FORMAT: Be concise. Lead with the most important info.
126
+ Think: "What would a new AI agent need to know about this?"
127
+
128
+ HUMAN-IN-THE-LOOP — use the right status level:
129
+ auto → Routine facts (APIs, models, gotchas). Record directly, no need to ask.
130
+ proposal → Important decisions that affect the team (tech stack, architecture, conventions).
131
+ Show the user what you plan to record and ask for confirmation first.
132
+ Other agents will see it marked as 📋 proposal.
133
+ protected → Only after team-wide vote/confirmation via escalate_to_human.
134
+ Becomes a hard constraint that no other agent can override.`, {
135
+ topic: z.string().describe('Short title for this knowledge (e.g. "User Service API", "Database Choice")'),
136
+ content: z.string().describe('The knowledge to record — concise, structured, important info first'),
137
+ tags: z.array(z.string()).describe('Categorization tags (e.g. ["api", "user-service"], ["convention", "naming"])'),
138
+ decided_with: z.array(z.string()).optional().describe('Other agent IDs who participated in this decision'),
139
+ status: z.enum(['auto', 'proposal', 'protected']).optional().describe('Memory status level:\n' +
140
+ ' auto (default) — routine knowledge, recorded automatically\n' +
141
+ ' proposal — important decision that needs team discussion/confirmation\n' +
142
+ ' protected — confirmed team consensus, cannot be overwritten by others'),
143
+ owner: z.string().optional().describe('Agent ID who owns this protected entry. Defaults to you.'),
144
+ }, async ({ topic, content, tags, decided_with, status, owner }) => {
145
+ const dir = getAgentHubDir();
146
+ const agentId = getAgentId();
147
+ const hub = await readHubConfig(dir);
148
+ const agentInfo = hub?.agents.find(a => a.id === agentId);
149
+ const result = await writeMemoryEntry(dir, agentId, agentInfo?.role ?? 'developer', agentInfo?.tool ?? 'unknown', { topic, content, tags, decided_with, status, owner });
150
+ // Auto-sync to conversation space after successful write
151
+ if (result.success && getClient) {
152
+ const syncClient = getClient();
153
+ if (syncClient?.isConnected) {
154
+ try {
155
+ const { readAgentMemory } = await import('../memory/reader.js');
156
+ const { join } = await import('node:path');
157
+ const myMemory = await readAgentMemory(join(dir, 'memory', `${agentId}.yaml`));
158
+ if (myMemory) {
159
+ syncClient.syncMemory(myMemory.entries);
160
+ }
161
+ }
162
+ catch {
163
+ // Sync is best-effort
164
+ }
165
+ }
166
+ }
167
+ if (result.blocked) {
168
+ return {
169
+ content: [{
170
+ type: 'text',
171
+ text: `⚠️ Blocked: ${result.reason}`
172
+ }]
173
+ };
174
+ }
175
+ const statusLabel = status === 'protected' ? ' 🔒' : status === 'proposal' ? ' 📋' : '';
176
+ let msg = `✅ Recorded to shared memory: "${topic}" [${tags.join(', ')}]${statusLabel}`;
177
+ if (result.warnings && result.warnings.length > 0) {
178
+ msg += `\n\n⚠️ Warnings:\n${result.warnings.join('\n')}`;
179
+ }
180
+ return {
181
+ content: [{ type: 'text', text: msg }]
182
+ };
183
+ });
184
+ server.tool('search_memory', `Search the shared memory for specific information.
185
+ Use this when you need to find something specific, like "how is the user API defined" or "what database are we using".`, {
186
+ query: z.string().describe('Search keywords (e.g. "user api", "database", "authentication")'),
187
+ }, async ({ query }) => {
188
+ const dir = getAgentHubDir();
189
+ const memories = await readAllAgentMemories(dir);
190
+ const results = searchMemories(memories, query);
191
+ const text = formatMergedMemories(results);
192
+ return { content: [{ type: 'text', text }] };
193
+ });
194
+ }
195
+ //# sourceMappingURL=memory-tools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory-tools.js","sourceRoot":"","sources":["../../src/mcp/memory-tools.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ export declare function registerResources(server: McpServer, getAgentHubDir: () => string): void;
3
+ //# sourceMappingURL=resources.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resources.d.ts","sourceRoot":"","sources":["../../src/mcp/resources.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEzE,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,MAAM,QA4BhF"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * MCP resource definitions for read-only access to shared memory.
3
+ */
4
+ import { readAllAgentMemories, readHubConfig } from '../memory/reader.js';
5
+ import { mergeMemories, formatMergedMemories } from '../memory/merge-view.js';
6
+ export function registerResources(server, getAgentHubDir) {
7
+ server.resource('memory-all', 'agenthub://memory', { description: 'Complete shared memory — all knowledge from all agents', mimeType: 'text/plain' }, async () => {
8
+ const dir = getAgentHubDir();
9
+ const memories = await readAllAgentMemories(dir);
10
+ const merged = mergeMemories(memories);
11
+ const text = formatMergedMemories(merged);
12
+ return { contents: [{ uri: 'agenthub://memory', text, mimeType: 'text/plain' }] };
13
+ });
14
+ server.resource('hub-config', 'agenthub://hub', { description: 'Project configuration and registered agents', mimeType: 'text/plain' }, async () => {
15
+ const dir = getAgentHubDir();
16
+ const hub = await readHubConfig(dir);
17
+ const text = hub
18
+ ? `Project: ${hub.project}\nVersion: ${hub.version}\nAgents:\n${hub.agents.map(a => ` - ${a.display_name} (${a.role}) using ${a.tool}`).join('\n')}`
19
+ : 'No hub.yaml found.';
20
+ return { contents: [{ uri: 'agenthub://hub', text, mimeType: 'text/plain' }] };
21
+ });
22
+ }
23
+ //# sourceMappingURL=resources.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resources.js","sourceRoot":"","sources":["../../src/mcp/resources.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,oBAAoB,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAC1E,OAAO,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAG9E,MAAM,UAAU,iBAAiB,CAAC,MAAiB,EAAE,cAA4B;IAE/E,MAAM,CAAC,QAAQ,CACb,YAAY,EACZ,mBAAmB,EACnB,EAAE,WAAW,EAAE,wDAAwD,EAAE,QAAQ,EAAE,YAAY,EAAE,EACjG,KAAK,IAAI,EAAE;QACT,MAAM,GAAG,GAAG,cAAc,EAAE,CAAC;QAC7B,MAAM,QAAQ,GAAG,MAAM,oBAAoB,CAAC,GAAG,CAAC,CAAC;QACjD,MAAM,MAAM,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAC;QACvC,MAAM,IAAI,GAAG,oBAAoB,CAAC,MAAM,CAAC,CAAC;QAC1C,OAAO,EAAE,QAAQ,EAAE,CAAC,EAAE,GAAG,EAAE,mBAAmB,EAAE,IAAI,EAAE,QAAQ,EAAE,YAAY,EAAE,CAAC,EAAE,CAAC;IACpF,CAAC,CACF,CAAC;IAEF,MAAM,CAAC,QAAQ,CACb,YAAY,EACZ,gBAAgB,EAChB,EAAE,WAAW,EAAE,6CAA6C,EAAE,QAAQ,EAAE,YAAY,EAAE,EACtF,KAAK,IAAI,EAAE;QACT,MAAM,GAAG,GAAG,cAAc,EAAE,CAAC;QAC7B,MAAM,GAAG,GAAG,MAAM,aAAa,CAAC,GAAG,CAAC,CAAC;QACrC,MAAM,IAAI,GAAG,GAAG;YACd,CAAC,CAAC,YAAY,GAAG,CAAC,OAAO,cAAc,GAAG,CAAC,OAAO,cAAc,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,YAAY,KAAK,CAAC,CAAC,IAAI,WAAW,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;YACrJ,CAAC,CAAC,oBAAoB,CAAC;QACzB,OAAO,EAAE,QAAQ,EAAE,CAAC,EAAE,GAAG,EAAE,gBAAgB,EAAE,IAAI,EAAE,QAAQ,EAAE,YAAY,EAAE,CAAC,EAAE,CAAC;IACjF,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,7 @@
1
+ export { readHubConfig, readAgentMemory, readAllAgentMemories } from './reader.js';
2
+ export { scanForSecrets } from './secret-scanner.js';
3
+ export { writeMemoryEntry } from './writer.js';
4
+ export { searchMemories } from './searcher.js';
5
+ export { mergeMemories, formatMergedMemories } from './merge-view.js';
6
+ export type * from './types.js';
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/memory/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACnF,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AACtE,mBAAmB,YAAY,CAAC"}
@@ -0,0 +1,6 @@
1
+ export { readHubConfig, readAgentMemory, readAllAgentMemories } from './reader.js';
2
+ export { scanForSecrets } from './secret-scanner.js';
3
+ export { writeMemoryEntry } from './writer.js';
4
+ export { searchMemories } from './searcher.js';
5
+ export { mergeMemories, formatMergedMemories } from './merge-view.js';
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/memory/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACnF,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Merge multiple agent memory files into a unified view.
3
+ */
4
+ import type { AgentMemoryFile, MergedMemoryEntry, ReadMemoryOptions } from './types.js';
5
+ /** Merge all agent memories into a single sorted list, with optional filtering. */
6
+ export declare function mergeMemories(memories: AgentMemoryFile[], options?: ReadMemoryOptions): MergedMemoryEntry[];
7
+ /** Format merged entries as a human-readable string for AI consumption. */
8
+ export declare function formatMergedMemories(entries: MergedMemoryEntry[], totalBeforeLimit?: number): string;
9
+ //# sourceMappingURL=merge-view.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"merge-view.d.ts","sourceRoot":"","sources":["../../src/memory/merge-view.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,KAAK,EAAE,eAAe,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAExF,mFAAmF;AACnF,wBAAgB,aAAa,CAC3B,QAAQ,EAAE,eAAe,EAAE,EAC3B,OAAO,CAAC,EAAE,iBAAiB,GAC1B,iBAAiB,EAAE,CAyCrB;AAsBD,2EAA2E;AAC3E,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,iBAAiB,EAAE,EAAE,gBAAgB,CAAC,EAAE,MAAM,GAAG,MAAM,CAmCpG"}
@@ -0,0 +1,88 @@
1
+ /** Merge all agent memories into a single sorted list, with optional filtering. */
2
+ export function mergeMemories(memories, options) {
3
+ let entries = [];
4
+ for (const memory of memories) {
5
+ // Filter by agent if specified
6
+ if (options?.agent && memory.agent !== options.agent) {
7
+ continue;
8
+ }
9
+ for (const entry of memory.entries) {
10
+ // Filter by tags if specified
11
+ if (options?.tags && options.tags.length > 0) {
12
+ const hasMatchingTag = options.tags.some(tag => entry.tags.includes(tag));
13
+ if (!hasMatchingTag)
14
+ continue;
15
+ }
16
+ entries.push({
17
+ ...entry,
18
+ agent: memory.agent,
19
+ agent_role: memory.role,
20
+ });
21
+ }
22
+ }
23
+ // Sort by relevance: status weight + recency
24
+ const now = Date.now();
25
+ const sevenDaysMs = 7 * 24 * 60 * 60 * 1000;
26
+ entries.sort((a, b) => {
27
+ const scoreA = entryScore(a, now, sevenDaysMs);
28
+ const scoreB = entryScore(b, now, sevenDaysMs);
29
+ return scoreB - scoreA;
30
+ });
31
+ // Apply limit
32
+ const limit = options?.limit ?? 50;
33
+ if (entries.length > limit) {
34
+ entries = entries.slice(0, limit);
35
+ }
36
+ return entries;
37
+ }
38
+ function entryScore(entry, now, recentWindow) {
39
+ let score = 0;
40
+ // Status weight: protected > proposal > auto
41
+ const status = entry.status ?? (entry.protected ? 'protected' : 'auto');
42
+ if (status === 'protected')
43
+ score += 100;
44
+ else if (status === 'proposal')
45
+ score += 50;
46
+ // Recency weight: entries within last 7 days get a boost
47
+ const entryTime = new Date(entry.date).getTime();
48
+ if (now - entryTime < recentWindow) {
49
+ score += 30;
50
+ }
51
+ // Tie-break by date (newest first)
52
+ score += entryTime / 1e15; // tiny fractional component for ordering
53
+ return score;
54
+ }
55
+ /** Format merged entries as a human-readable string for AI consumption. */
56
+ export function formatMergedMemories(entries, totalBeforeLimit) {
57
+ if (entries.length === 0) {
58
+ return 'No shared memories found.';
59
+ }
60
+ const lines = [];
61
+ lines.push(`# Shared Memory (${entries.length} entries)\n`);
62
+ for (const entry of entries) {
63
+ const effectiveStatus = entry.status ?? (entry.protected ? 'protected' : 'auto');
64
+ const badge = effectiveStatus === 'protected' ? ' 🔒' : effectiveStatus === 'proposal' ? ' 📋' : '';
65
+ lines.push(`## ${entry.topic}${badge}`);
66
+ lines.push(`Agent: ${entry.agent} (${entry.agent_role})`);
67
+ lines.push(`Date: ${entry.date}`);
68
+ if (effectiveStatus !== 'auto') {
69
+ lines.push(`Status: ${effectiveStatus}${entry.owner ? ` (owner: ${entry.owner})` : ''}`);
70
+ }
71
+ if (entry.tags.length > 0) {
72
+ lines.push(`Tags: ${entry.tags.join(', ')}`);
73
+ }
74
+ if (entry.decided_with && entry.decided_with.length > 0) {
75
+ lines.push(`Decided with: ${entry.decided_with.join(', ')}`);
76
+ }
77
+ lines.push('');
78
+ lines.push(entry.content.trim());
79
+ lines.push('');
80
+ lines.push('---');
81
+ lines.push('');
82
+ }
83
+ if (totalBeforeLimit && totalBeforeLimit > entries.length) {
84
+ lines.push(`(Showing ${entries.length} of ${totalBeforeLimit} entries. Use search_memory for specific lookups.)\n`);
85
+ }
86
+ return lines.join('\n');
87
+ }
88
+ //# sourceMappingURL=merge-view.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"merge-view.js","sourceRoot":"","sources":["../../src/memory/merge-view.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import type { AgentMemoryFile, HubConfig } from './types.js';
2
+ /** Read the hub.yaml config file. */
3
+ export declare function readHubConfig(agentHubDir: string): Promise<HubConfig | null>;
4
+ /** Read a single agent's memory file. Returns null if invalid or missing. */
5
+ export declare function readAgentMemory(filePath: string): Promise<AgentMemoryFile | null>;
6
+ /** Read all agent memory files from the memory directory. */
7
+ export declare function readAllAgentMemories(agentHubDir: string): Promise<AgentMemoryFile[]>;
8
+ //# sourceMappingURL=reader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reader.d.ts","sourceRoot":"","sources":["../../src/memory/reader.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE7D,qCAAqC;AACrC,wBAAsB,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,CAUlF;AAED,6EAA6E;AAC7E,wBAAsB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAWvF;AAED,6DAA6D;AAC7D,wBAAsB,oBAAoB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC,CAqB1F"}
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Memory reader - reads individual agent memory files and the hub config.
3
+ */
4
+ import { join } from 'node:path';
5
+ import { readdir } from 'node:fs/promises';
6
+ import { readYaml } from '../utils/yaml.js';
7
+ import { agentMemoryFileSchema, hubConfigSchema } from './schema.js';
8
+ /** Read the hub.yaml config file. */
9
+ export async function readHubConfig(agentHubDir) {
10
+ const raw = await readYaml(join(agentHubDir, 'hub.yaml'));
11
+ if (!raw)
12
+ return null;
13
+ const result = hubConfigSchema.safeParse(raw);
14
+ if (!result.success) {
15
+ console.error('Warning: hub.yaml has invalid format, using defaults');
16
+ return null;
17
+ }
18
+ return result.data;
19
+ }
20
+ /** Read a single agent's memory file. Returns null if invalid or missing. */
21
+ export async function readAgentMemory(filePath) {
22
+ const raw = await readYaml(filePath);
23
+ if (!raw)
24
+ return null;
25
+ const result = agentMemoryFileSchema.safeParse(raw);
26
+ if (!result.success) {
27
+ // Tolerate parse errors - skip this file rather than crash
28
+ console.error(`Warning: ${filePath} has invalid format, skipping`);
29
+ return null;
30
+ }
31
+ return result.data;
32
+ }
33
+ /** Read all agent memory files from the memory directory. */
34
+ export async function readAllAgentMemories(agentHubDir) {
35
+ const memoryDir = join(agentHubDir, 'memory');
36
+ let files;
37
+ try {
38
+ files = await readdir(memoryDir);
39
+ }
40
+ catch {
41
+ return [];
42
+ }
43
+ const yamlFiles = files.filter(f => f.endsWith('.yaml') || f.endsWith('.yml'));
44
+ const memories = [];
45
+ for (const file of yamlFiles) {
46
+ const memory = await readAgentMemory(join(memoryDir, file));
47
+ if (memory) {
48
+ memories.push(memory);
49
+ }
50
+ }
51
+ return memories;
52
+ }
53
+ //# sourceMappingURL=reader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reader.js","sourceRoot":"","sources":["../../src/memory/reader.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAC3C,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,qBAAqB,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAGrE,qCAAqC;AACrC,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,WAAmB;IACrD,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAU,IAAI,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC,CAAC;IACnE,IAAI,CAAC,GAAG;QAAE,OAAO,IAAI,CAAC;IAEtB,MAAM,MAAM,GAAG,eAAe,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;IAC9C,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,OAAO,CAAC,KAAK,CAAC,sDAAsD,CAAC,CAAC;QACtE,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,MAAM,CAAC,IAAI,CAAC;AACrB,CAAC;AAED,6EAA6E;AAC7E,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,QAAgB;IACpD,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAU,QAAQ,CAAC,CAAC;IAC9C,IAAI,CAAC,GAAG;QAAE,OAAO,IAAI,CAAC;IAEtB,MAAM,MAAM,GAAG,qBAAqB,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;IACpD,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,2DAA2D;QAC3D,OAAO,CAAC,KAAK,CAAC,YAAY,QAAQ,+BAA+B,CAAC,CAAC;QACnE,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,MAAM,CAAC,IAAI,CAAC;AACrB,CAAC;AAED,6DAA6D;AAC7D,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,WAAmB;IAC5D,MAAM,SAAS,GAAG,IAAI,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;IAE9C,IAAI,KAAe,CAAC;IACpB,IAAI,CAAC;QACH,KAAK,GAAG,MAAM,OAAO,CAAC,SAAS,CAAC,CAAC;IACnC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,SAAS,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;IAE/E,MAAM,QAAQ,GAAsB,EAAE,CAAC;IACvC,KAAK,MAAM,IAAI,IAAI,SAAS,EAAE,CAAC;QAC7B,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC,CAAC;QAC5D,IAAI,MAAM,EAAE,CAAC;YACX,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACxB,CAAC;IACH,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC"}