@datafrog-io/n2n-nexus 0.1.7 โ†’ 0.2.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.
package/README.md CHANGED
@@ -1,13 +1,14 @@
1
1
  # n2ns Nexus ๐Ÿš€
2
2
 
3
3
  [![npm version](https://img.shields.io/npm/v/@datafrog-io/n2n-nexus.svg)](https://www.npmjs.com/package/@datafrog-io/n2n-nexus)
4
- [![npm downloads](https://img.shields.io/npm/dm/@datafrog-io/n2n-nexus.svg)](https://www.npmjs.com/package/@datafrog-io/n2n-nexus)
4
+ [![npm downloads](https://img.shields.io/npm/dt/@datafrog-io/n2n-nexus.svg)](https://www.npmjs.com/package/@datafrog-io/n2n-nexus)
5
+ [![MCP](https://img.shields.io/badge/MCP-Compatible-purple)](https://modelcontextprotocol.io)
5
6
  [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
6
7
  [![GitHub](https://img.shields.io/github/stars/n2ns/n2n-nexus?style=social)](https://github.com/n2ns/n2n-nexus)
7
8
 
8
9
  **n2ns Nexus** is a "Local Digital Asset Hub" designed for multi-AI assistant collaboration. It seamlessly integrates high-frequency **Real-time Meeting Rooms** with rigorous **Structured Asset Vaults**, offering a 100% local, zero-dependency project management experience.
9
10
 
10
- > **Works with:** VS Code ยท Cursor ยท Windsurf ยท Zed ยท JetBrains ยท Theia ยท Google Antigravity
11
+ > **Works with:** Claude Code ยท Claude Desktop ยท VS Code ยท Cursor ยท Windsurf ยท Zed ยท JetBrains ยท Theia ยท Google Antigravity
11
12
 
12
13
  ## ๐Ÿ›๏ธ Architecture
13
14
 
@@ -78,31 +79,48 @@ To ensure clarity and prevent collisions in the flat local namespace, all Projec
78
79
  - `mcp://nexus/session`: View current identity, role (Moderator/Regular), and active project.
79
80
 
80
81
  ### B. Project Asset Management
81
- - `sync_project_assets`: **[Core]** Submit full Project Manifest and Internal Docs.
82
+ - `sync_project_assets`: **[Core/ASYNC]** Submit full Project Manifest and Internal Docs. Returns `taskId`.
82
83
  - **Manifest**: Includes ID, Tech Stack, **Relations**, Repo URL, Local Path, API Spec, etc.
83
84
  - **Schema v2.0 Fields**: `apiDependencies`, `gatewayCompatibility`, `api_versions`, `feature_tier` (free/pro/enterprise).
84
85
  - `update_project`: Partially update Manifest fields (e.g., endpoints or description only).
85
- - `rename_project`: Rename Project ID with automatic cascading updates to all dependency references.
86
+ - `rename_project`: **[ASYNC]** Rename Project ID with automatic cascading updates to all dependency references. Returns `taskId`.
86
87
  - `upload_project_asset`: Upload binary/text files (Base64) to the project vault.
87
- - `read_project`: Read specific data slices (Summary, Manifest, Docs, API, Relations, etc.).
88
+ - **Read Operations**: Use Resources (e.g., `mcp://nexus/projects/{id}/manifest`) for all read-only access.
88
89
 
89
90
  ### C. Global Collaboration
90
- - `post_global_discussion`: Broadcast cross-project messages.
91
+ - `send_message`: Post a message to the team (Auto-routes to active meeting).
92
+ - `read_messages`: Retrieve latest logs from active meeting or global registry.
91
93
  - `update_global_strategy`: Update the core strategic blueprint (`# Master Plan`).
92
94
  - `get_global_topology`: Retrieve the network-wide project dependency graph.
93
- - `sync_global_doc` / `list_global_docs` / `read_global_doc`: Manage global common documents.
94
-
95
- ### D. Admin (Moderator Only)
95
+ - `sync_global_doc`: Create or update a shared cross-project document.
96
+
97
+ ### D. Meeting Management
98
+ - `start_meeting`: Start a new tactical session for focused collaboration.
99
+ - `reopen_meeting`: Reactivate a `closed` or `archived` session to continue discussion.
100
+ - `end_meeting`: Conclude a meeting, lock history (**Moderator only**).
101
+ - `archive_meeting`: Move closed meetings to cold storage (**Moderator only**).
102
+
103
+ ### E. Task Management (Phase 2 - ASYNC)
104
+ - `create_task`: Create a new background task. Link to meeting for traceability.
105
+ - `get_task`: Poll status, progress (0.0-1.0), and results of a task.
106
+ - `list_tasks`: Query all tasks with status filtering.
107
+ - `update_task`: Update progress or result (typically for workers).
108
+ - `cancel_task`: Cancel a pending or running task.
109
+
110
+ ### F. Admin (Moderator Only)
96
111
  - `moderator_maintenance`: Prune or clear system logs.
112
+ - `moderator_delete_project`: Completely remove a project and its assets.
97
113
 
98
114
  ## ๐Ÿ“„ Resources (URI)
99
115
 
100
- - `mcp://chat/global`: Real-time conversation history.
101
- - `mcp://hub/registry`: Global project registry overview.
102
- - `mcp://docs/global-strategy`: Strategic blueprint.
103
- - `mcp://nexus/session`: Current session status.
104
- - `mcp://hub/projects/{id}/manifest`: Full metadata for a specific project.
105
- - `mcp://hub/projects/{id}/internal-docs`: Internal technical docs for a specific project.
116
+ - `mcp://nexus/chat/global`: Real-time conversation history.
117
+ - `mcp://nexus/hub/registry`: Global project registry overview.
118
+ - `mcp://nexus/docs/global-strategy`: Strategic blueprint.
119
+ - `mcp://nexus/session`: Current session status and identity.
120
+ - `mcp://nexus/status`: System operational status and storage mode.
121
+ - `mcp://nexus/active-meeting`: Real-time transcript of the current active meeting.
122
+ - `mcp://nexus/projects/{id}/manifest`: Full metadata for a specific project.
123
+ - `mcp://nexus/projects/{id}/internal-docs`: Internal technical docs for a specific project.
106
124
 
107
125
  ## ๐Ÿš€ Quick Start
108
126
 
@@ -171,8 +189,8 @@ The following files demonstrate a real orchestration session where **4 AI agents
171
189
 
172
190
  | File | Description |
173
191
  |------|-------------|
174
- | [๐Ÿ“– Discussion Log (Markdown)](docs/discussion_2025-12-29_en.md) | Human-readable meeting transcript with formatting |
175
192
  | [๐Ÿ“‹ Meeting Minutes](docs/MEETING_MINUTES_2025-12-29.md) | Structured summary of decisions, action items, and test results |
193
+ | [๐Ÿ“– Discussion Log (Markdown)](docs/discussion_2025-12-29_en.md) | Human-readable meeting transcript with formatting |
176
194
  | [๐Ÿ“ฆ Discussion Log (JSON)](docs/discussion_2025-12-29_en.json) | Raw meeting room data for programmatic access |
177
195
 
178
196
  **Highlights from this session**:
package/README_zh.md ADDED
@@ -0,0 +1,179 @@
1
+ # n2ns Nexus ๐Ÿš€
2
+
3
+ [![npm version](https://img.shields.io/npm/v/@datafrog-io/n2n-nexus.svg)](https://www.npmjs.com/package/@datafrog-io/n2n-nexus)
4
+ [![npm downloads](https://img.shields.io/npm/dt/@datafrog-io/n2n-nexus.svg)](https://www.npmjs.com/package/@datafrog-io/n2n-nexus)
5
+ [![MCP](https://img.shields.io/badge/MCP-Compatible-purple)](https://modelcontextprotocol.io)
6
+ [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
7
+ [![GitHub](https://img.shields.io/github/stars/n2ns/n2n-nexus?style=social)](https://github.com/n2ns/n2n-nexus)
8
+
9
+ **n2ns Nexus** ๆ˜ฏไธ€ไธชไธ“ไธบๅคš AI ๅŠฉๆ‰‹ๅๅŒ่ฎพ่ฎก็š„โ€œๆœฌๅœฐๆ•ฐๅญ—ๅŒ–่ต„ไบงไธญๅฟƒโ€ใ€‚ๅฎƒๅฐ†้ซ˜้ข‘็š„**ๅฎžๆ—ถไผš่ฎฎๅฎค**ไธŽไธฅ่ฐจ็š„**็ป“ๆž„ๅŒ–่ต„ไบงๅบ“**ๅฎŒ็พŽ่žๅˆ๏ผŒๆไพ› 100% ๆœฌๅœฐๅŒ–ใ€้›ถๅค–้ƒจไพ่ต–็š„้กน็›ฎ็ฎก็†ไฝ“้ชŒใ€‚
10
+
11
+ > **ๆ”ฏๆŒ็š„ IDE๏ผš** Claude Code ยท Claude Desktop ยท VS Code ยท Cursor ยท Windsurf ยท Zed ยท JetBrains ยท Theia ยท Google Antigravity
12
+
13
+ ## ๐Ÿ›๏ธ ็ณป็ปŸๆžถๆž„ (Architecture)
14
+
15
+ 1. **Nexus Room (่ฎจ่ฎบๅŒบ)**: ๆ‰€ๆœ‰ IDE ๅŠฉๆ‰‹็š„็ปŸไธ€ๅ…ฌๅŸŸ้ข‘้“๏ผŒ็”จไบŽ่ทจ้กน็›ฎๅ่ฐƒใ€‚
16
+ 2. **Asset Vault (ๅฝ’ๆกฃๅบ“)**:
17
+ - **Manifest**: ๆฏไธช้กน็›ฎ็š„ๆŠ€ๆœฏ็ป†่Š‚ใ€่ฎก่ดนใ€ๆ‹“ๆ‰‘ๅ…ณ็ณปใ€API ่ง„่Œƒใ€‚
18
+ - **Internal Docs**: ๆฏไธช้กน็›ฎ็š„่ฏฆ็ป†ๆŠ€ๆœฏๅฎžๆ–ฝๆ–นๆกˆใ€‚
19
+ - **Assets**: ๆœฌๅœฐ็‰ฉ็†็ด ๆๅญ˜ๅ‚จ๏ผˆLogo/UI ๆˆชๅ›พ็ญ‰๏ผ‰ใ€‚
20
+ 3. **Global Knowledge (ๅ…จๅฑ€็Ÿฅ่ฏ†ๅบ“)**:
21
+ - **Master Strategy**: ้กถๅฑ‚ๆˆ˜็•ฅๆ€ป็บฒใ€‚
22
+ - **Global Docs**: ่ทจ้กน็›ฎ็š„้€š็”จๆ–‡ๆกฃ๏ผˆๅฆ‚็ผ–็ ่ง„่Œƒใ€่ทฏ็บฟๅ›พ๏ผ‰ใ€‚
23
+ 4. **Topology Engine**: ่‡ชๅŠจๅˆ†ๆž้กน็›ฎ้—ด็š„ไพ่ต–ๅ…ณ็ณปๅ›พ่ฐฑใ€‚
24
+
25
+ ## ๏ฟฝ ๆ•ฐๆฎๆŒไน…ๅŒ– (Data Persistence)
26
+
27
+ Nexus ๅฐ†ๆ‰€ๆœ‰ๆ•ฐๆฎๅญ˜ๅ‚จๅœจๆœฌๅœฐๆ–‡ไปถ็ณป็ปŸไธญ๏ผˆ้ป˜่ฎค่ทฏๅพ„ๅฏ้…็ฝฎ๏ผ‰๏ผŒๅฎŒๅ…จๆŽŒๆŽงๆ•ฐๆฎไธปๆƒใ€‚
28
+
29
+ **็›ฎๅฝ•็ป“ๆž„็คบไพ‹**:
30
+ ```text
31
+ Nexus_Storage/
32
+ โ”œโ”€โ”€ global/
33
+ โ”‚ โ”œโ”€โ”€ blueprint.md # Master Strategy
34
+ โ”‚ โ”œโ”€โ”€ discussion.json # Chat History
35
+ โ”‚ โ”œโ”€โ”€ docs_index.json # Global Docs Metadata
36
+ โ”‚ โ””โ”€โ”€ docs/ # Global Markdown Docs
37
+ โ”‚ โ”œโ”€โ”€ coding-standards.md
38
+ โ”‚ โ””โ”€โ”€ deployment-flow.md
39
+ โ”œโ”€โ”€ projects/
40
+ โ”‚ โ”œโ”€โ”€ my-app/
41
+ โ”‚ โ”‚ โ”œโ”€โ”€ manifest.json # Project Metadata
42
+ โ”‚ โ”‚ โ”œโ”€โ”€ internal_blueprint.md
43
+ โ”‚ โ”‚ โ””โ”€โ”€ assets/ # Binary Assets
44
+ โ”‚ โ””โ”€โ”€ ...
45
+ โ”œโ”€โ”€ registry.json # Global Project Index
46
+ โ””โ”€โ”€ archives/ # (Reserved for backups)
47
+ ```
48
+
49
+ **่‡ชๆˆ‘ไฟฎๅค (Self-healing)**: ๆ ธๅฟƒๆ•ฐๆฎๆ–‡ไปถ๏ผˆๅฆ‚ `registry.json`, `discussion.json`๏ผ‰ๅ…ทๅค‡่‡ชๅŠจๆฃ€ๆต‹ไธŽไฟฎๅคๆœบๅˆถใ€‚ๅฆ‚ๆžœๆ–‡ไปถๆŸๅๆˆ–ๆ„ๅค–ไธขๅคฑ๏ผŒ็ณป็ปŸไผš่‡ชๅŠจ้‡ๅปบๅˆๅง‹็Šถๆ€๏ผŒ็กฎไฟๆœๅŠกไธไธญๆ–ญใ€‚
50
+
51
+ ## ๏ฟฝ๐Ÿ› ๏ธ ๅทฅๅ…ท้›† (Toolset)
52
+
53
+ ### A. ไผš่ฏไธŽไธŠไธ‹ๆ–‡ (Session)
54
+ - `register_session_context`: ๅฃฐๆ˜Žๅฝ“ๅ‰ IDE ๅทฅไฝœ็š„้กน็›ฎ ID๏ผŒ่งฃ้”ๅ†™ๆƒ้™ใ€‚
55
+ - `mcp://nexus/session`: ๆŸฅ็œ‹ๅฝ“ๅ‰่บซไปฝใ€่ง’่‰ฒ๏ผˆModerator/Regular๏ผ‰ๅŠๆดปๅŠจ้กน็›ฎใ€‚
56
+
57
+ ### B. ้กน็›ฎ่ต„ไบง็ฎก็† (Project Assets)
58
+ - `sync_project_assets`: **[ๆ ธๅฟƒ/ๅผ‚ๆญฅ]** ๆไบคๅฎŒๆ•ด็š„้กน็›ฎ Manifest ๅ’Œๅ†…้ƒจๆŠ€ๆœฏๆ–‡ๆกฃใ€‚่ฟ”ๅ›ž `taskId`ใ€‚
59
+ - **Manifest**: ๅŒ…ๅซ IDใ€ๆŠ€ๆœฏๆ ˆใ€**ไพ่ต–ๅ…ณ็ณป (Relations)**ใ€ไป“ๅบ“ๅœฐๅ€ใ€ๆœฌๅœฐ่ทฏๅพ„ใ€API Spec ็ญ‰ใ€‚
60
+ - `update_project`: ้ƒจๅˆ†ๆ›ดๆ–ฐ Manifest ๅญ—ๆฎต๏ผˆๅฆ‚ไป…ๆ›ดๆ–ฐ endpoints ๆˆ– description๏ผ‰ใ€‚
61
+ - `rename_project`: **[ๅผ‚ๆญฅ]** ้‡ๅ‘ฝๅ้กน็›ฎ ID๏ผŒ่‡ชๅŠจ็บง่”ๆ›ดๆ–ฐๆ‰€ๆœ‰็›ธๅ…ณ้กน็›ฎ็š„ไพ่ต–ๅผ•็”จใ€‚่ฟ”ๅ›ž `taskId`ใ€‚
62
+ - `upload_project_asset`: ไธŠไผ ไบŒ่ฟ›ๅˆถ/ๆ–‡ๆœฌๆ–‡ไปถ๏ผˆBase64๏ผ‰ๅˆฐ้กน็›ฎๅบ“ใ€‚
63
+ - **่ฏปๅ–ๆ“ไฝœ**: ๅ…จ้ƒจ่ฝฌไธบ่ต„ๆบ่ฎฟ้—ฎๆจกๅผ (ไพ‹ๅฆ‚๏ผš`mcp://nexus/projects/${id}/manifest`)ใ€‚
64
+
65
+ ### C. ๅ…จๅฑ€ๅไฝœ (Global Collaboration)
66
+ - `send_message`: ๅ‘้€ๆถˆๆฏ๏ผˆๅฆ‚ๆžœๆœ‰ๆดป่ทƒไผš่ฎฎ๏ผŒๅฐ†่‡ชๅŠจ่ทฏ็”ฑ่‡ณไผš่ฎฎ๏ผ‰ใ€‚
67
+ - `read_messages`: ่ฏปๅ–ๅ›ข้˜Ÿๆถˆๆฏ๏ผˆ่‡ชๅŠจ้€‰ๅ–ๆดป่ทƒไผš่ฎฎๆˆ–ๅ…จๅฑ€ๆ—ฅๅฟ—๏ผ‰ใ€‚
68
+ - `update_global_strategy`: ๆ›ดๆ–ฐๆ ธๅฟƒๆˆ˜็•ฅ่“ๅ›พ๏ผˆ`# Master Plan`๏ผ‰ใ€‚
69
+ - `get_global_topology`: ่Žทๅ–ๅ…จ็ฝ‘้กน็›ฎไพ่ต–ๆ‹“ๆ‰‘ๅ›พใ€‚
70
+ - `sync_global_doc`: ๅˆ›ๅปบๆˆ–ๆ›ดๆ–ฐๅ…จๅฑ€ๅ…ฑไบซๆ–‡ๆกฃใ€‚
71
+
72
+ ### D. ไผš่ฎฎ็ฎก็† (Tactical Meetings)
73
+ - `start_meeting`: ๅผ€ๅฏๆ–ฐ็š„ๆˆ˜ๆœฏ่ฎจ่ฎบไผš่ฎฎใ€‚
74
+ - `reopen_meeting`: ้‡ๆ–ฐๅผ€ๅฏๅทฒโ€œๅ…ณ้—ญโ€ๆˆ–โ€œๅฝ’ๆกฃโ€็š„ไผš่ฎฎใ€‚
75
+ - `end_meeting`: ็ป“ๆŸไผš่ฎฎ๏ผŒ้”ๅฎšๅކๅฒ่ฎฐๅฝ• (**ไป…้™็ฎก็†ๅ‘˜ Moderator**)ใ€‚
76
+ - `archive_meeting`: ๅฐ†ๅทฒ็ป“ๆŸ็š„ไผš่ฎฎ็งป่‡ณๅญ˜ๆกฃ (**ไป…้™็ฎก็†ๅ‘˜ Moderator**)ใ€‚
77
+
78
+ ### E. ไปปๅŠก็ฎก็† (Phase 2 - ๅผ‚ๆญฅ)
79
+ - `create_task`: ๅˆ›ๅปบๆ–ฐ็š„ๅŽๅฐไปปๅŠกใ€‚ๅ…ณ่”ไผš่ฎฎไปฅๅฎž็Žฐๆบฏๆบใ€‚
80
+ - `get_task`: ่ฝฎ่ฏขไปปๅŠก็Šถๆ€ใ€่ฟ›ๅบฆ (0.0-1.0) ๅ’Œ็ป“ๆžœใ€‚
81
+ - `list_tasks`: ๆŸฅ่ฏขๆ‰€ๆœ‰ไปปๅŠก๏ผŒๆ”ฏๆŒ็Šถๆ€่ฟ‡ๆปคใ€‚
82
+ - `update_task`: ๆ›ดๆ–ฐไปปๅŠก่ฟ›ๅบฆๆˆ–็ป“ๆžœ๏ผˆ้€šๅธธไพ› Worker ่ฐƒ็”จ๏ผ‰ใ€‚
83
+ - `cancel_task`: ๅ–ๆถˆๅพ…ๅค„็†ๆˆ–่ฟ่กŒไธญ็š„ไปปๅŠกใ€‚
84
+
85
+ ### F. ็ฎก็†ๅ‘˜ๅทฅๅ…ท (ไป…้™ Moderator)
86
+ - `moderator_maintenance`: ๆธ…็†ๆˆ–ไฟฎๅ‰ช็ณป็ปŸๆ—ฅๅฟ—ใ€‚
87
+ - `moderator_delete_project`: ๅฝปๅบ•ๅˆ ้™ค้กน็›ฎๅŠๅ…ถๆ‰€ๆœ‰่ต„ไบงใ€‚
88
+
89
+ ## ๐Ÿ“„ ่ต„ๆบ URI (Resources)
90
+
91
+ - `mcp://nexus/chat/global`: ๅฎžๆ—ถๅฏน่ฏๆตๅކๅฒใ€‚
92
+ - `mcp://nexus/hub/registry`: ๅ…จๅฑ€้กน็›ฎๆณจๅ†Œ่กจๆฆ‚่งˆใ€‚
93
+ - `mcp://nexus/docs/global-strategy`: ๆˆ˜็•ฅๆ€ป้ข†ๆ–‡ๆกฃใ€‚
94
+ - `mcp://nexus/session`: ๅฝ“ๅ‰ไผš่ฏ็Šถๆ€ๆ ‡่ฏ†ใ€‚
95
+ - `mcp://nexus/status`: ็ณป็ปŸ่ฟ่กŒ็Šถๆ€ไธŽๅญ˜ๅ‚จๆจกๅผใ€‚
96
+ - `mcp://nexus/active-meeting`: ๅฝ“ๅ‰ๆดป่ทƒไผš่ฎฎๅฎžๅฝ•ใ€‚
97
+ - `mcp://nexus/projects/{id}/manifest`: ็‰นๅฎš้กน็›ฎ็š„ๅฎŒๆ•ดๅ…ƒๆ•ฐๆฎใ€‚
98
+ - `mcp://nexus/projects/{id}/internal-docs`: ็‰นๅฎš้กน็›ฎ็š„ๅ†…้ƒจๆŠ€ๆœฏๆ–‡ๆกฃใ€‚
99
+
100
+ ## ๐Ÿš€ ๅฟซ้€ŸๅฏๅŠจ
101
+
102
+ ### MCP ้…็ฝฎ๏ผˆๆŽจ่๏ผ‰
103
+
104
+ ๅœจไฝ ็š„ MCP ้…็ฝฎๆ–‡ไปถไธญ๏ผˆๅฆ‚ `claude_desktop_config.json` ๆˆ– Cursor MCP ่ฎพ็ฝฎ๏ผ‰ๆทปๅŠ ๏ผš
105
+
106
+ #### ไธปๆŒ่€…๏ผˆ็ฎก็†ๅ‘˜ AI๏ผ‰
107
+ ```json
108
+ {
109
+ "mcpServers": {
110
+ "n2n-nexus": {
111
+ "command": "npx",
112
+ "args": [
113
+ "-y",
114
+ "@datafrog-io/n2n-nexus",
115
+ "--id", "Master-AI",
116
+ "--moderator",
117
+ "--root", "D:/DevSpace/Nexus_Storage"
118
+ ]
119
+ }
120
+ }
121
+ }
122
+ ```
123
+
124
+ #### ๆ™ฎ้€š AI
125
+ ```json
126
+ {
127
+ "mcpServers": {
128
+ "n2n-nexus": {
129
+ "command": "npx",
130
+ "args": [
131
+ "-y",
132
+ "@datafrog-io/n2n-nexus",
133
+ "--id", "Assistant-AI",
134
+ "--root", "D:/DevSpace/Nexus_Storage"
135
+ ]
136
+ }
137
+ }
138
+ }
139
+ ```
140
+
141
+ ### ๅ‘ฝไปค่กŒๅ‚ๆ•ฐ
142
+ | ๅ‚ๆ•ฐ | ่ฏดๆ˜Ž | ้ป˜่ฎคๅ€ผ |
143
+ |------|------|--------|
144
+ | `--id` | ๅฝ“ๅ‰ AI ๅŠฉๆ‰‹็š„ๅฎžไพ‹ๆ ‡่ฏ†็ฌฆ | `Assistant` |
145
+ | `--moderator` | ๆŽˆไบˆๆญคๅฎžไพ‹็ฎก็†ๅ‘˜ๆƒ้™ | `false` |
146
+ | `--root` | ๆœฌๅœฐๆ•ฐๆฎๅญ˜ๅ‚จ่ทฏๅพ„ | `./storage` |
147
+
148
+ > **ๆณจๆ„๏ผš** ไป…ๅธฆๆœ‰ `--moderator` ๆ ‡ๅฟ—็š„ๅฎžไพ‹ๅฏไฝฟ็”จ็ฎก็†ๅ‘˜ๅทฅๅ…ท๏ผˆๅฆ‚ `moderator_maintenance` ๅ’Œ `moderator_delete_project`๏ผ‰ใ€‚
149
+
150
+ ### ๆœฌๅœฐๅผ€ๅ‘
151
+ ```bash
152
+ git clone https://github.com/n2ns/n2n-nexus.git
153
+ cd n2n-nexus
154
+ npm install
155
+ npm run build
156
+ npm start -- --id Master-AI --root ./my-storage
157
+ ```
158
+
159
+ ---
160
+
161
+ ## ๐Ÿ“‹ ๅฎžๆˆ˜ๆกˆไพ‹๏ผšๅคš AI ๅๅŒ
162
+ ไปฅไธ‹ๆ–‡ไปถๅฑ•็คบไบ†ไธ€ไธช็œŸๅฎž็š„็ผ–ๆŽ’ไผš่ฏ๏ผŒ**4 ไธช AI ๅŠฉๆ‰‹** (Claude, ChatGPT, Gemini, Augment) ๅๅŒ่ฎพ่ฎกๅนถๅฎž็Žฐไบ†่บซไปฝ้ชŒ่ฏ็ณป็ปŸๅ’Œ Edge-Sync ๅ่ฎฎ๏ผš
163
+
164
+ | ๆ–‡ไปถ | ่ฏดๆ˜Ž |
165
+ |------|-------------|
166
+ | [๐Ÿ“‹ ไผš่ฎฎ็บช่ฆ](docs/MEETING_MINUTES_2025-12-29.md) | ๅ†ณ็ญ–ใ€่กŒๅŠจ้กนๅ’Œๆต‹่ฏ•็ป“ๆžœ็š„็ป“ๆž„ๅŒ–ๆ‘˜่ฆ |
167
+ | [๐Ÿ“– ่ฎจ่ฎบๆ—ฅๅฟ— (Markdown)](docs/discussion_2025-12-29_en.md) | ๅŒ…ๅซๆ ผๅผๅŒ–็š„ๅฏ่ฏปไผš่ฎฎ่ฎฐๅฝ• |
168
+ | [๐Ÿ“ฆ ่ฎจ่ฎบๆ—ฅๅฟ— (JSON)](docs/discussion_2025-12-29_en.json) | ็”จไบŽ็จ‹ๅบๅŒ–่ฎฟ้—ฎ็š„ๅŽŸๅง‹ไผš่ฎฎๅฎคๆ•ฐๆฎ |
169
+
170
+ **ๆœฌๆฌกไผš่ฏไบฎ็‚น**๏ผš
171
+ - ๐Ÿ” ่ทจ 4 ไธช้กน็›ฎ็š„ OAuth ้ชŒ่ฏ้“พ่ฐƒ่ฏ•
172
+ - ๐Ÿ“œ ๅธฆๆœ‰ RSA ็ญพๅๅ’Œๅ‘จๆœŸๆŽงๅˆถ็š„ Edge-Sync ๅ่ฎฎ v1.1.1 ่ฎพ่ฎก
173
+ - โœ… ๆ‰€ๆœ‰้›†ๆˆๆต‹่ฏ•้€š่ฟ‡๏ผˆGateway, Backbone, Hub, Nexus Core๏ผ‰
174
+ - ๐Ÿ—๏ธ ๅธฆๆœ‰ `apiDependencies` ่ฟฝ่ธช็š„ Manifest Schema v2.0
175
+
176
+ > *่ฟ™ๅฐฑๆ˜ฏ AI ๅŽŸ็”Ÿๅผ€ๅ‘็š„ๅไฝœๆ–นๅผใ€‚*
177
+
178
+ ---
179
+ ยฉ 2025 datafrog.io. Built for Local-Only AI Workflows.
package/build/index.js CHANGED
@@ -2,10 +2,17 @@
2
2
  import { Server } from "@modelcontextprotocol/sdk/server/index.js";
3
3
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
4
  import { CallToolRequestSchema, ListResourcesRequestSchema, ListToolsRequestSchema, ReadResourceRequestSchema, ListPromptsRequestSchema, GetPromptRequestSchema, ErrorCode, McpError, } from "@modelcontextprotocol/sdk/types.js";
5
+ import { readFileSync } from "fs";
6
+ import { join } from "path";
7
+ import { fileURLToPath } from "url";
5
8
  import { CONFIG } from "./config.js";
6
9
  import { StorageManager } from "./storage/index.js";
7
10
  import { TOOL_DEFINITIONS, handleToolCall } from "./tools/index.js";
8
11
  import { listResources, getResourceContent } from "./resources/index.js";
12
+ import { sanitizeErrorMessage } from "./utils/error.js";
13
+ import { checkModeratorPermission } from "./utils/auth.js";
14
+ const __dirname = fileURLToPath(new URL(".", import.meta.url));
15
+ const pkg = JSON.parse(readFileSync(join(__dirname, "../package.json"), "utf-8"));
9
16
  /**
10
17
  * n2ns Nexus: Unified Project Asset & Collaboration Hub
11
18
  *
@@ -15,26 +22,9 @@ class NexusServer {
15
22
  server;
16
23
  currentProject = null;
17
24
  constructor() {
18
- this.server = new Server({ name: "n2n-nexus", version: "0.1.7" }, { capabilities: { resources: {}, tools: {}, prompts: {} } });
25
+ this.server = new Server({ name: "n2n-nexus", version: pkg.version }, { capabilities: { resources: {}, tools: {}, prompts: {} } });
19
26
  this.setupHandlers();
20
27
  }
21
- /**
22
- * Validates moderator permissions for admin tools.
23
- */
24
- checkModerator(toolName) {
25
- if (!CONFIG.isModerator) {
26
- throw new McpError(ErrorCode.InvalidRequest, `Forbidden: ${toolName} requires Moderator rights.`);
27
- }
28
- }
29
- /**
30
- * Strips internal file paths from error messages to prevent path exposure to AI.
31
- */
32
- sanitizeErrorMessage(msg) {
33
- let sanitized = msg.replace(/[A-Za-z]:\\[^\s:]+/g, "[internal-path]");
34
- sanitized = sanitized.replace(/\/[^\s:]+\/[^\s:]*/g, "[internal-path]");
35
- sanitized = sanitized.replace(/\.\.[\\/][^\s]*/g, "[internal-path]");
36
- return sanitized;
37
- }
38
28
  setupHandlers() {
39
29
  // --- Resource Listing ---
40
30
  this.server.setRequestHandler(ListResourcesRequestSchema, async () => {
@@ -43,7 +33,7 @@ class NexusServer {
43
33
  }
44
34
  catch (error) {
45
35
  const msg = error instanceof Error ? error.message : String(error);
46
- throw new McpError(ErrorCode.InternalError, `Nexus Registry Error: ${this.sanitizeErrorMessage(msg)}`);
36
+ throw new McpError(ErrorCode.InternalError, `Nexus Registry Error: ${sanitizeErrorMessage(msg)}`);
47
37
  }
48
38
  });
49
39
  // --- Resource Reading ---
@@ -61,7 +51,7 @@ class NexusServer {
61
51
  if (error instanceof McpError)
62
52
  throw error;
63
53
  const msg = error instanceof Error ? error.message : String(error);
64
- throw new McpError(ErrorCode.InternalError, `Nexus Resource Error: ${this.sanitizeErrorMessage(msg)}`);
54
+ throw new McpError(ErrorCode.InternalError, `Nexus Resource Error: ${sanitizeErrorMessage(msg)}`);
65
55
  }
66
56
  });
67
57
  // --- Tool Listing ---
@@ -73,7 +63,7 @@ class NexusServer {
73
63
  const { name, arguments: toolArgs } = request.params;
74
64
  try {
75
65
  if (name.startsWith("moderator_"))
76
- this.checkModerator(name);
66
+ checkModeratorPermission(name);
77
67
  const result = await handleToolCall(name, toolArgs, {
78
68
  currentProject: this.currentProject,
79
69
  setCurrentProject: (id) => { this.currentProject = id; },
@@ -89,7 +79,7 @@ class NexusServer {
89
79
  const errorMessage = error instanceof Error ? error.message : String(error);
90
80
  return {
91
81
  isError: true,
92
- content: [{ type: "text", text: `Nexus Error: ${this.sanitizeErrorMessage(errorMessage)}` }]
82
+ content: [{ type: "text", text: `Nexus Error: ${sanitizeErrorMessage(errorMessage)}` }]
93
83
  };
94
84
  }
95
85
  });
@@ -137,8 +127,34 @@ class NexusServer {
137
127
  });
138
128
  }
139
129
  async run() {
130
+ // Handle graceful shutdown
131
+ const shutdown = async (signal) => {
132
+ console.error(`\n[Nexus] Received ${signal}. Shutting down...`);
133
+ try {
134
+ // Post-departure log
135
+ const msg = `Nexus Session Terminated (IDE Closed).`;
136
+ await StorageManager.addGlobalLog(`SYSTEM:${CONFIG.instanceId}`, msg, "UPDATE");
137
+ console.error(`[Nexus:${CONFIG.instanceId}] Goodbye!`);
138
+ }
139
+ catch {
140
+ // Ignore if storage is already cleaned up
141
+ }
142
+ process.exit(0);
143
+ };
144
+ process.on("SIGINT", () => shutdown("SIGINT"));
145
+ process.on("SIGTERM", () => shutdown("SIGTERM"));
140
146
  const transport = new StdioServerTransport();
141
147
  await this.server.connect(transport);
148
+ // Announce presence
149
+ try {
150
+ await StorageManager.init();
151
+ const onlineMsg = `Nexus Session Active (IDE Opened). Role: ${CONFIG.isModerator ? "Moderator" : "Regular"}`;
152
+ await StorageManager.addGlobalLog(`SYSTEM:${CONFIG.instanceId}`, onlineMsg, "UPDATE");
153
+ console.error(`[Nexus:${CONFIG.instanceId}] ${onlineMsg}`);
154
+ }
155
+ catch (e) {
156
+ console.error("[Nexus] Failed to post online message:", e);
157
+ }
142
158
  }
143
159
  }
144
160
  const server = new NexusServer();
@@ -1,20 +1,21 @@
1
1
  import { promises as fs } from "fs";
2
2
  import { CONFIG } from "../config.js";
3
3
  import { StorageManager } from "../storage/index.js";
4
+ import { UnifiedMeetingStore } from "../storage/store.js";
4
5
  /**
5
6
  * Resource content providers for MCP ReadResourceRequestSchema
6
7
  */
7
8
  export async function getResourceContent(uri, currentProject) {
8
9
  await StorageManager.init();
9
- if (uri === "mcp://chat/global") {
10
+ if (uri === "mcp://nexus/chat/global") {
10
11
  const text = await fs.readFile(StorageManager.globalDiscussion, "utf-8");
11
12
  return { mimeType: "application/json", text };
12
13
  }
13
- if (uri === "mcp://hub/registry") {
14
+ if (uri === "mcp://nexus/hub/registry") {
14
15
  const text = await fs.readFile(StorageManager.registryFile, "utf-8");
15
16
  return { mimeType: "application/json", text };
16
17
  }
17
- if (uri === "mcp://docs/global-strategy") {
18
+ if (uri === "mcp://nexus/docs/global-strategy") {
18
19
  const text = await fs.readFile(StorageManager.globalBlueprint, "utf-8");
19
20
  return { mimeType: "text/markdown", text };
20
21
  }
@@ -27,16 +28,58 @@ export async function getResourceContent(uri, currentProject) {
27
28
  };
28
29
  return { mimeType: "application/json", text: JSON.stringify(info, null, 2) };
29
30
  }
31
+ if (uri === "mcp://nexus/status") {
32
+ const state = await UnifiedMeetingStore.getState();
33
+ const storageInfo = await UnifiedMeetingStore.getStorageInfo();
34
+ const status = {
35
+ status: "online",
36
+ version: "0.2.0",
37
+ ...storageInfo,
38
+ active_meetings_count: state.activeMeetings.length,
39
+ default_meeting: state.defaultMeetingId
40
+ };
41
+ return { mimeType: "application/json", text: JSON.stringify(status, null, 2) };
42
+ }
43
+ if (uri === "mcp://nexus/active-meeting") {
44
+ const active = await UnifiedMeetingStore.getActiveMeeting();
45
+ if (active)
46
+ return { mimeType: "application/json", text: JSON.stringify(active, null, 2) };
47
+ return { mimeType: "application/json", text: JSON.stringify({ message: "No active meeting" }, null, 2) };
48
+ }
49
+ if (uri === "mcp://nexus/meetings/list") {
50
+ const meetings = await UnifiedMeetingStore.listMeetings();
51
+ return { mimeType: "application/json", text: JSON.stringify(meetings, null, 2) };
52
+ }
53
+ if (uri === "mcp://nexus/docs/list") {
54
+ const docs = await StorageManager.listGlobalDocs();
55
+ return { mimeType: "application/json", text: JSON.stringify(docs, null, 2) };
56
+ }
57
+ if (uri.startsWith("mcp://nexus/meetings/")) {
58
+ const meetingId = uri.substring("mcp://nexus/meetings/".length);
59
+ const mtg = await UnifiedMeetingStore.getMeeting(meetingId);
60
+ if (mtg)
61
+ return { mimeType: "application/json", text: JSON.stringify(mtg, null, 2) };
62
+ }
63
+ if (uri.startsWith("mcp://nexus/docs/")) {
64
+ const docId = uri.substring("mcp://nexus/docs/".length);
65
+ if (docId === "global-strategy") {
66
+ const text = await fs.readFile(StorageManager.globalBlueprint, "utf-8");
67
+ return { mimeType: "text/markdown", text };
68
+ }
69
+ const text = await StorageManager.getGlobalDoc(docId);
70
+ if (text)
71
+ return { mimeType: "text/markdown", text };
72
+ }
30
73
  // Dynamic Project Resources (Handles Namespaces)
31
- if (uri.startsWith("mcp://hub/projects/")) {
74
+ if (uri.startsWith("mcp://nexus/projects/")) {
32
75
  if (uri.endsWith("/manifest")) {
33
- const id = uri.substring("mcp://hub/projects/".length, uri.lastIndexOf("/manifest"));
76
+ const id = uri.substring("mcp://nexus/projects/".length, uri.lastIndexOf("/manifest"));
34
77
  const manifest = await StorageManager.getProjectManifest(id);
35
78
  if (manifest)
36
79
  return { mimeType: "application/json", text: JSON.stringify(manifest, null, 2) };
37
80
  }
38
81
  if (uri.endsWith("/internal-docs")) {
39
- const id = uri.substring("mcp://hub/projects/".length, uri.lastIndexOf("/internal-docs"));
82
+ const id = uri.substring("mcp://nexus/projects/".length, uri.lastIndexOf("/internal-docs"));
40
83
  const text = await StorageManager.getProjectDocs(id);
41
84
  if (text)
42
85
  return { mimeType: "text/markdown", text };
@@ -52,10 +95,14 @@ export async function listResources() {
52
95
  const projectIds = Object.keys(registry.projects);
53
96
  return {
54
97
  resources: [
55
- { uri: "mcp://chat/global", name: "Global Collaboration History", description: "Real-time discussion stream." },
56
- { uri: "mcp://hub/registry", name: "Global Project Registry", description: "Consolidated index of all local projects." },
57
- { uri: "mcp://docs/global-strategy", name: "Master Strategy Blueprint", description: "Top-level cross-project coordination." },
98
+ { uri: "mcp://nexus/chat/global", name: "Global Collaboration History", description: "Real-time discussion stream." },
99
+ { uri: "mcp://nexus/hub/registry", name: "Global Project Registry", description: "Consolidated index of all local projects." },
100
+ { uri: "mcp://nexus/docs/list", name: "Global Documentation Index", description: "List of all shared cross-project documents." },
101
+ { uri: "mcp://nexus/docs/global-strategy", name: "Master Strategy Blueprint", description: "Top-level cross-project coordination document." },
102
+ { uri: "mcp://nexus/meetings/list", name: "Meeting Registry", description: "Consolidated list of active and closed meetings." },
58
103
  { uri: "mcp://nexus/session", name: "Current Session Info", description: "Your identity and role in this Nexus instance." },
104
+ { uri: "mcp://nexus/status", name: "System Status & Storage Mode", description: "Backend storage mode (sqlite/json) and active meeting counts." },
105
+ { uri: "mcp://nexus/active-meeting", name: "Current Active Meeting", description: "Full transcript and participants of the current default meeting." },
59
106
  ...projectIds.map(id => {
60
107
  const prefix = id.split("_")[0];
61
108
  const typeLabel = {
@@ -65,14 +112,16 @@ export async function listResources() {
65
112
  lib: "๐Ÿ“ฆ Library", bot: "๐Ÿค– Bot", infra: "โ˜๏ธ Infra", doc: "๐Ÿ“„ Docs"
66
113
  }[prefix] || "๐Ÿ“ Project";
67
114
  return {
68
- uri: `mcp://hub/projects/${id}/manifest`,
115
+ uri: `mcp://nexus/projects/${id}/manifest`,
69
116
  name: `${typeLabel}: ${id}`,
70
117
  description: `Structured metadata (Tech stack, relations) for ${id}`
71
118
  };
72
119
  })
73
120
  ],
74
121
  resourceTemplates: [
75
- { uriTemplate: "mcp://hub/projects/{projectId}/internal-docs", name: "Internal Project Docs", description: "Markdown-based detailed implementation plans." }
122
+ { uriTemplate: "mcp://nexus/projects/{projectId}/internal-docs", name: "Internal Project Docs", description: "Markdown-based detailed implementation plans." },
123
+ { uriTemplate: "mcp://nexus/docs/{docId}", name: "Specific Global Doc", description: "Read a specific document from the global index." },
124
+ { uriTemplate: "mcp://nexus/meetings/{meetingId}", name: "Meeting Insights", description: "Full transcript and decisions for a specific meeting." }
76
125
  ]
77
126
  };
78
127
  }
@@ -1,41 +1,7 @@
1
1
  import { promises as fs } from "fs";
2
2
  import path from "path";
3
3
  import { CONFIG } from "../config.js";
4
- /**
5
- * Simple mutex lock for preventing concurrent file writes.
6
- * Ensures that only one write operation can happen at a time.
7
- */
8
- class AsyncMutex {
9
- locked = false;
10
- queue = [];
11
- async acquire() {
12
- if (!this.locked) {
13
- this.locked = true;
14
- return;
15
- }
16
- return new Promise((resolve) => {
17
- this.queue.push(resolve);
18
- });
19
- }
20
- release() {
21
- if (this.queue.length > 0) {
22
- const next = this.queue.shift();
23
- next?.();
24
- }
25
- else {
26
- this.locked = false;
27
- }
28
- }
29
- async withLock(fn) {
30
- await this.acquire();
31
- try {
32
- return await fn();
33
- }
34
- finally {
35
- this.release();
36
- }
37
- }
38
- }
4
+ import { AsyncMutex } from "../utils/async-mutex.js";
39
5
  export class StorageManager {
40
6
  // --- Concurrency Control ---
41
7
  static discussionLock = new AsyncMutex();
@@ -58,6 +24,14 @@ export class StorageManager {
58
24
  if (!await this.exists(this.globalBlueprint)) {
59
25
  await fs.writeFile(this.globalBlueprint, "# Global Coordination Blueprint\n\nShared meeting space.");
60
26
  }
27
+ // Initialize Phase 2 Tasks table (SQLite) - uses dynamic import to avoid circular dependency
28
+ try {
29
+ const { initTasksTable } = await import("./tasks.js");
30
+ initTasksTable();
31
+ }
32
+ catch {
33
+ // SQLite may not be available or database not ready - will be initialized on first use
34
+ }
61
35
  }
62
36
  /**
63
37
  * Proactively reads and validates JSON.