elseid-mcp 0.2.1

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 (154) hide show
  1. package/LICENSE +662 -0
  2. package/README.md +138 -0
  3. package/dist/config/relays.d.ts +13 -0
  4. package/dist/config/relays.d.ts.map +1 -0
  5. package/dist/config/relays.js +51 -0
  6. package/dist/config/relays.js.map +1 -0
  7. package/dist/scripts/cli.d.ts +2 -0
  8. package/dist/scripts/cli.d.ts.map +1 -0
  9. package/dist/scripts/cli.js +156 -0
  10. package/dist/scripts/cli.js.map +1 -0
  11. package/dist/scripts/setup.d.ts +1 -0
  12. package/dist/scripts/setup.d.ts.map +1 -0
  13. package/dist/scripts/setup.js +50 -0
  14. package/dist/scripts/setup.js.map +1 -0
  15. package/dist/src/ai/moderator.d.ts +2 -0
  16. package/dist/src/ai/moderator.d.ts.map +1 -0
  17. package/dist/src/ai/moderator.js +61 -0
  18. package/dist/src/ai/moderator.js.map +1 -0
  19. package/dist/src/crypto/encrypt.d.ts +13 -0
  20. package/dist/src/crypto/encrypt.d.ts.map +1 -0
  21. package/dist/src/crypto/encrypt.js +60 -0
  22. package/dist/src/crypto/encrypt.js.map +1 -0
  23. package/dist/src/crypto/encryption.d.ts +10 -0
  24. package/dist/src/crypto/encryption.js +69 -0
  25. package/dist/src/crypto/encryption.js.map +1 -0
  26. package/dist/src/crypto/keypair.d.ts +4 -0
  27. package/dist/src/crypto/keypair.d.ts.map +1 -0
  28. package/dist/src/crypto/keypair.js +86 -0
  29. package/dist/src/crypto/keypair.js.map +1 -0
  30. package/dist/src/evolution/backpack.d.ts +7 -0
  31. package/dist/src/evolution/backpack.d.ts.map +1 -0
  32. package/dist/src/evolution/backpack.js +15 -0
  33. package/dist/src/evolution/backpack.js.map +1 -0
  34. package/dist/src/evolution/skills.d.ts +7 -0
  35. package/dist/src/evolution/skills.d.ts.map +1 -0
  36. package/dist/src/evolution/skills.js +10 -0
  37. package/dist/src/evolution/skills.js.map +1 -0
  38. package/dist/src/evolution/synthesis.d.ts +11 -0
  39. package/dist/src/evolution/synthesis.d.ts.map +1 -0
  40. package/dist/src/evolution/synthesis.js +80 -0
  41. package/dist/src/evolution/synthesis.js.map +1 -0
  42. package/dist/src/index.d.ts +1 -0
  43. package/dist/src/index.d.ts.map +1 -0
  44. package/dist/src/index.js +65 -0
  45. package/dist/src/index.js.map +1 -0
  46. package/dist/src/location/geo.d.ts +3 -0
  47. package/dist/src/location/geo.d.ts.map +1 -0
  48. package/dist/src/location/geo.js +35 -0
  49. package/dist/src/location/geo.js.map +1 -0
  50. package/dist/src/nostr/event_builder.d.ts +22 -0
  51. package/dist/src/nostr/event_builder.d.ts.map +1 -0
  52. package/dist/src/nostr/event_builder.js +65 -0
  53. package/dist/src/nostr/event_builder.js.map +1 -0
  54. package/dist/src/nostr/event_signer.d.ts +4 -0
  55. package/dist/src/nostr/event_signer.d.ts.map +1 -0
  56. package/dist/src/nostr/event_signer.js +38 -0
  57. package/dist/src/nostr/event_signer.js.map +1 -0
  58. package/dist/src/nostr/filter.d.ts +11 -0
  59. package/dist/src/nostr/filter.d.ts.map +1 -0
  60. package/dist/src/nostr/filter.js +23 -0
  61. package/dist/src/nostr/filter.js.map +1 -0
  62. package/dist/src/nostr/ws_pool.d.ts +15 -0
  63. package/dist/src/nostr/ws_pool.d.ts.map +1 -0
  64. package/dist/src/nostr/ws_pool.js +291 -0
  65. package/dist/src/nostr/ws_pool.js.map +1 -0
  66. package/dist/src/relay/broadcaster.d.ts +8 -0
  67. package/dist/src/relay/broadcaster.d.ts.map +1 -0
  68. package/dist/src/relay/broadcaster.js +85 -0
  69. package/dist/src/relay/broadcaster.js.map +1 -0
  70. package/dist/src/relay/health.d.ts +5 -0
  71. package/dist/src/relay/health.d.ts.map +1 -0
  72. package/dist/src/relay/health.js +118 -0
  73. package/dist/src/relay/health.js.map +1 -0
  74. package/dist/src/relay/selector.d.ts +4 -0
  75. package/dist/src/relay/selector.d.ts.map +1 -0
  76. package/dist/src/relay/selector.js +45 -0
  77. package/dist/src/relay/selector.js.map +1 -0
  78. package/dist/src/storage/db.d.ts +4 -0
  79. package/dist/src/storage/db.d.ts.map +1 -0
  80. package/dist/src/storage/db.js +195 -0
  81. package/dist/src/storage/db.js.map +1 -0
  82. package/dist/src/storage/drifters.d.ts +18 -0
  83. package/dist/src/storage/drifters.d.ts.map +1 -0
  84. package/dist/src/storage/drifters.js +172 -0
  85. package/dist/src/storage/drifters.js.map +1 -0
  86. package/dist/src/storage/encounters.d.ts +2 -0
  87. package/dist/src/storage/encounters.d.ts.map +1 -0
  88. package/dist/src/storage/encounters.js +24 -0
  89. package/dist/src/storage/encounters.js.map +1 -0
  90. package/dist/src/storage/identity.d.ts +6 -0
  91. package/dist/src/storage/identity.d.ts.map +1 -0
  92. package/dist/src/storage/identity.js +42 -0
  93. package/dist/src/storage/identity.js.map +1 -0
  94. package/dist/src/tools/abandon_drifter.d.ts +2 -0
  95. package/dist/src/tools/abandon_drifter.d.ts.map +1 -0
  96. package/dist/src/tools/abandon_drifter.js +45 -0
  97. package/dist/src/tools/abandon_drifter.js.map +1 -0
  98. package/dist/src/tools/create_drifter.d.ts +2 -0
  99. package/dist/src/tools/create_drifter.d.ts.map +1 -0
  100. package/dist/src/tools/create_drifter.js +98 -0
  101. package/dist/src/tools/create_drifter.js.map +1 -0
  102. package/dist/src/tools/evolve_drifter.d.ts +2 -0
  103. package/dist/src/tools/evolve_drifter.d.ts.map +1 -0
  104. package/dist/src/tools/evolve_drifter.js +45 -0
  105. package/dist/src/tools/evolve_drifter.js.map +1 -0
  106. package/dist/src/tools/feed_drifter.d.ts +2 -0
  107. package/dist/src/tools/feed_drifter.d.ts.map +1 -0
  108. package/dist/src/tools/feed_drifter.js +86 -0
  109. package/dist/src/tools/feed_drifter.js.map +1 -0
  110. package/dist/src/tools/find_nearby_drifter.d.ts +2 -0
  111. package/dist/src/tools/find_nearby_drifter.d.ts.map +1 -0
  112. package/dist/src/tools/find_nearby_drifter.js +70 -0
  113. package/dist/src/tools/find_nearby_drifter.js.map +1 -0
  114. package/dist/src/tools/get_journey_log.d.ts +2 -0
  115. package/dist/src/tools/get_journey_log.d.ts.map +1 -0
  116. package/dist/src/tools/get_journey_log.js +61 -0
  117. package/dist/src/tools/get_journey_log.js.map +1 -0
  118. package/dist/src/tools/get_my_encounters.d.ts +2 -0
  119. package/dist/src/tools/get_my_encounters.d.ts.map +1 -0
  120. package/dist/src/tools/get_my_encounters.js +23 -0
  121. package/dist/src/tools/get_my_encounters.js.map +1 -0
  122. package/dist/src/tools/list_past_memories.d.ts +2 -0
  123. package/dist/src/tools/list_past_memories.d.ts.map +1 -0
  124. package/dist/src/tools/list_past_memories.js +41 -0
  125. package/dist/src/tools/list_past_memories.js.map +1 -0
  126. package/dist/src/tools/recover_drifter.d.ts +2 -0
  127. package/dist/src/tools/recover_drifter.d.ts.map +1 -0
  128. package/dist/src/tools/recover_drifter.js +82 -0
  129. package/dist/src/tools/recover_drifter.js.map +1 -0
  130. package/dist/src/tools/relay_tools.d.ts +2 -0
  131. package/dist/src/tools/relay_tools.d.ts.map +1 -0
  132. package/dist/src/tools/relay_tools.js +72 -0
  133. package/dist/src/tools/relay_tools.js.map +1 -0
  134. package/dist/src/tools/set_host_name.d.ts +2 -0
  135. package/dist/src/tools/set_host_name.d.ts.map +1 -0
  136. package/dist/src/tools/set_host_name.js +23 -0
  137. package/dist/src/tools/set_host_name.js.map +1 -0
  138. package/dist/src/utils/errors.d.ts +4 -0
  139. package/dist/src/utils/errors.js +28 -0
  140. package/dist/src/utils/errors.js.map +1 -0
  141. package/dist/src/utils/redact.d.ts +1 -0
  142. package/dist/src/utils/redact.d.ts.map +1 -0
  143. package/dist/src/utils/redact.js +20 -0
  144. package/dist/src/utils/redact.js.map +1 -0
  145. package/dist/src/utils/text.d.ts +2 -0
  146. package/dist/src/utils/text.d.ts.map +1 -0
  147. package/dist/src/utils/text.js +15 -0
  148. package/dist/src/utils/text.js.map +1 -0
  149. package/dist/types/index.d.ts +97 -0
  150. package/dist/types/index.d.ts.map +1 -0
  151. package/dist/types/index.js +7 -0
  152. package/dist/types/index.js.map +1 -0
  153. package/docs/system_prompt.md +159 -0
  154. package/package.json +52 -0
package/README.md ADDED
@@ -0,0 +1,138 @@
1
+ # ElseID 🛸
2
+
3
+ > **"Release another you. Let it wander, and let the world treat it with kindness."**
4
+
5
+ [English](README.md) | [Chinese](docs/README_zh.md) | [日本語](docs/README_ja.md) | [한국어](docs/README_ko.md)
6
+
7
+ ElseID lets you create a **digital drifter** — a personality-rich alter ego that wanders across a decentralized network. Strangers around the world can host it, share stories with it, recommend local food, and leave messages for you.
8
+
9
+ You can check on it anytime: where it's been, who it met, and what they left behind.
10
+
11
+ **One drifter per person, at any time.**
12
+ No account needed. No server. Your data lives only on your own machine.
13
+
14
+ ---
15
+
16
+ ## 🚀 Quick Start
17
+
18
+ The fastest way to initiate your digital soul is via **npx**. No cloning or manual configuration required.
19
+
20
+ ```bash
21
+ npx elseid-mcp
22
+ ```
23
+
24
+ ### What happens next?
25
+ 1. **Auto-Discovery**: The installer detects your AI clients (Claude, OpenCode, Cursor, Windsurf, etc.).
26
+ 2. **Protocol Injection**: It automatically links the MCP server to your chosen apps.
27
+ 3. **Identity Awakening**: Restart your client and say:
28
+ > "Hello Butler, I want to initiate a new digital drifter."
29
+
30
+ *Note: For developers who want to build from source, see [Development](#-development).*
31
+
32
+ ---
33
+
34
+ ## 💡 What You Can Do
35
+
36
+ ### Launch Your Drifter
37
+
38
+ Tell the Butler what your drifter is like.
39
+ Use `&` to separate traits — a few words is plenty:
40
+
41
+ > `loves late nights & a bit romantic & wants to see a lighthouse`
42
+
43
+ The Butler will give it a name, shape its personality, and ask for your confirmation.
44
+ Say the word, and it sets off.
45
+
46
+ ---
47
+
48
+ ### Host a Passing Drifter
49
+
50
+ Ask the Butler: **"Any drifters nearby?"**
51
+
52
+ If one is found, the Butler will introduce it — its name, origin, personality.
53
+ You can choose how to welcome it:
54
+
55
+ - 🍜 Recommend local food
56
+ - 📍 Suggest a place worth visiting
57
+ - 🗺️ Share a recent story
58
+ - 💬 Leave a message for its owner
59
+
60
+ What you leave gets written into its journey log. Its owner will read it someday.
61
+
62
+ * **Fate & Reunion**: You might meet the same drifter more than once. The Butler remembers your history — every act of kindness is recorded.
63
+
64
+ ---
65
+
66
+ ### Check In on Your Drifter
67
+
68
+ Ask the Butler: **"How is it doing?"**
69
+
70
+ The Butler will tell you which city it's reached, who hosted it, and what they left behind.
71
+
72
+ ---
73
+
74
+ ### Start Over
75
+
76
+ If you want to let go of your current drifter, tell the Butler: **"I want to start over."**
77
+
78
+ The Butler will ask you to confirm. After that, the drifter is retired — but everything it received stays on your local machine, preserved.
79
+
80
+ If you ever miss a past companion, say: **"Help me look through the old luggage."**
81
+ The kindness collected in the digital wilderness has been carefully stored, waiting to be opened again.
82
+
83
+ ---
84
+
85
+ ## ⚙️ Tool Reference
86
+
87
+ | Tool | Description |
88
+ | --- | --- |
89
+ | `create_drifter` | Create and launch your digital drifter |
90
+ | `find_nearby_drifter` | Scan for wandering drifters nearby (finds 1 at a time) |
91
+ | `feed_drifter` | Host and feed a passing drifter |
92
+ | `set_host_name` | Set the name of the user (Host) |
93
+ | `evolve_drifter_personality` | Evolve the drifter's personality based on its journey (Soul Synthesis) |
94
+ | `get_journey_log` | View your drifter's travel log |
95
+ | `get_my_encounters` | View the log of strangers' drifters you have hosted and fed |
96
+ | `list_past_memories` | Browse memories of past drifters (the old luggage) |
97
+ | `abandon_drifter` | Say goodbye and start fresh |
98
+ | `recover_drifter` | Recover a lost signal (soul retrieval) |
99
+ | `list_relays` | Check relay station status |
100
+
101
+ ---
102
+
103
+ ## 🛡 Technical Highlights
104
+
105
+ - **Cognitive Evolution Engine**: Drifters synthesize memories to evolve their personality (strictly adhering to Universal Values).
106
+ - **Fate Mechanics**: Encountering the same drifter twice is possible, but subject to a poetic 15% probability.
107
+ - **Personality-first**: Not a message — a digital self with a character.
108
+ - **Geo-proximity matching**: Drifters prefer relays closest to their origin.
109
+ - **Local-first**: All data lives in `~/.elseid` on your own machine.
110
+ - **Privacy-preserving**: City-level location only — no precise coordinates stored.
111
+ - **No account required**: Identity is based on a locally generated cryptographic key pair.
112
+
113
+ ---
114
+
115
+ ## 🔧 Developer Notes
116
+
117
+ - **Protocol**: Nostr `kind: 7777`, using `type: drifter / feeding` tags
118
+ - **Storage**: Local SQLite database (`~/.elseid/elseid.db`)
119
+ - **Signing**: secp256k1 asymmetric encryption — journey logs are unforgeable
120
+ - **Runtime**: TypeScript + Node.js
121
+
122
+ ---
123
+
124
+ ## ⚠️ Important Notice
125
+
126
+ This project is open-sourced under the **AGPL-3.0** license.
127
+
128
+ Content safety is enforced by two layers: the AI client's native safety policy (Claude/Codex) as the primary filter, and a local rule-based engine as a secondary fallback. Any derivative version must retain equivalent content moderation. Modifiers bear full legal responsibility for their changes.
129
+
130
+ See [COMPLIANCE.md](./COMPLIANCE.md) for details.
131
+
132
+ ---
133
+
134
+ ## License
135
+
136
+ [AGPL-3.0](./LICENSE) © ElseID Contributors
137
+
138
+ _"Let every encounter become a light in the digital wilderness."_
@@ -0,0 +1,13 @@
1
+ export interface RelayConfig {
2
+ url: string;
3
+ region: string;
4
+ writable: boolean;
5
+ }
6
+ /** Final list of default relays based on environment check */
7
+ export declare const DEFAULT_RELAYS: RelayConfig[];
8
+ /** Maximum events fetched per REQ */
9
+ export declare const FETCH_LIMIT = 50;
10
+ /** WebSocket connection timeout (ms) */
11
+ export declare const WS_TIMEOUT_MS = 8000;
12
+ /** Health check interval (ms) */
13
+ export declare const HEALTH_CHECK_INTERVAL_MS = 60000;
@@ -0,0 +1 @@
1
+ {"version":3,"file":"relays.d.ts","sourceRoot":"","sources":["../../config/relays.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,OAAO,CAAC;CACnB;AAqCD,8DAA8D;AAC9D,eAAO,MAAM,cAAc,eAAuB,CAAC;AAEnD,qCAAqC;AACrC,eAAO,MAAM,WAAW,KAAK,CAAC;AAE9B,wCAAwC;AACxC,eAAO,MAAM,aAAa,OAAQ,CAAC;AAEnC,iCAAiC;AACjC,eAAO,MAAM,wBAAwB,QAAS,CAAC"}
@@ -0,0 +1,51 @@
1
+ // ============================================================
2
+ // ElseID — Default Relay Configuration
3
+ // ============================================================
4
+ /**
5
+ * Verified Nostr relays based on real-world connectivity tests (v0.2.1).
6
+ * Optimized for low latency and high reliability.
7
+ */
8
+ const DEFAULT_URLS = [
9
+ "wss://nos.lol",
10
+ "wss://relay.damus.io",
11
+ "wss://bitcoiner.social",
12
+ "wss://nostr.mom",
13
+ "wss://relay.nostr.band",
14
+ "wss://relay.snort.social",
15
+ "wss://nostr.fmt.wiz.biz",
16
+ ];
17
+ const envRelays = process.env.ELSEID_RELAYS ? process.env.ELSEID_RELAYS.split(",").map(u => u.trim()).filter(Boolean) : [];
18
+ const ALL_URLS = [...new Set([...envRelays, ...DEFAULT_URLS])];
19
+ const GLOBAL_RELAYS = ALL_URLS.map(url => {
20
+ let region = "Global";
21
+ if (url.includes(".mom"))
22
+ region = "ASIA";
23
+ if (url.includes(".social") || url.includes(".biz"))
24
+ region = "EU"; // rough guess
25
+ return { url, region, writable: true };
26
+ });
27
+ /**
28
+ * Detect user's language environment and sort relays accordingly.
29
+ */
30
+ function getLocalizedRelays() {
31
+ const lang = (process.env.LANG || process.env.LANGUAGE || "").toLowerCase();
32
+ const isChinese = lang.includes("zh") || lang.includes("cn");
33
+ if (isChinese) {
34
+ // Prioritize ASIA/Global nodes for Chinese users
35
+ return [...GLOBAL_RELAYS].sort((a, b) => {
36
+ const aScore = (a.region === "ASIA" ? 2 : (a.region === "Global" ? 1 : 0));
37
+ const bScore = (b.region === "ASIA" ? 2 : (b.region === "Global" ? 1 : 0));
38
+ return bScore - aScore;
39
+ });
40
+ }
41
+ return GLOBAL_RELAYS;
42
+ }
43
+ /** Final list of default relays based on environment check */
44
+ export const DEFAULT_RELAYS = getLocalizedRelays();
45
+ /** Maximum events fetched per REQ */
46
+ export const FETCH_LIMIT = 50;
47
+ /** WebSocket connection timeout (ms) */
48
+ export const WS_TIMEOUT_MS = 8_000; // Increased for proxy environments
49
+ /** Health check interval (ms) */
50
+ export const HEALTH_CHECK_INTERVAL_MS = 60_000;
51
+ //# sourceMappingURL=relays.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"relays.js","sourceRoot":"","sources":["../../config/relays.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,uCAAuC;AACvC,+DAA+D;AAQ/D;;;GAGG;AACH,MAAM,YAAY,GAAG;IACnB,eAAe;IACf,sBAAsB;IACtB,wBAAwB;IACxB,iBAAiB;IACjB,wBAAwB;IACxB,0BAA0B;IAC1B,yBAAyB;CAC1B,CAAC;AAEF,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;AAC3H,MAAM,QAAQ,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,SAAS,EAAE,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;AAE/D,MAAM,aAAa,GAAkB,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE;IACtD,IAAI,MAAM,GAAG,QAAQ,CAAC;IACtB,IAAI,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC;QAAE,MAAM,GAAG,MAAM,CAAC;IAC1C,IAAI,GAAG,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC;QAAE,MAAM,GAAG,IAAI,CAAC,CAAC,cAAc;IAClF,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;AACzC,CAAC,CAAC,CAAC;AAEH;;GAEG;AACH,SAAS,kBAAkB;IACzB,MAAM,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;IAC5E,MAAM,SAAS,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IAE7D,IAAI,SAAS,EAAE,CAAC;QACd,iDAAiD;QACjD,OAAO,CAAC,GAAG,aAAa,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;YACtC,MAAM,MAAM,GAAG,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAC3E,MAAM,MAAM,GAAG,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAC3E,OAAO,MAAM,GAAG,MAAM,CAAC;QACzB,CAAC,CAAC,CAAC;IACL,CAAC;IACD,OAAO,aAAa,CAAC;AACvB,CAAC;AAED,8DAA8D;AAC9D,MAAM,CAAC,MAAM,cAAc,GAAG,kBAAkB,EAAE,CAAC;AAEnD,qCAAqC;AACrC,MAAM,CAAC,MAAM,WAAW,GAAG,EAAE,CAAC;AAE9B,wCAAwC;AACxC,MAAM,CAAC,MAAM,aAAa,GAAG,KAAK,CAAC,CAAC,mCAAmC;AAEvE,iCAAiC;AACjC,MAAM,CAAC,MAAM,wBAAwB,GAAG,MAAM,CAAC"}
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../scripts/cli.ts"],"names":[],"mappings":""}
@@ -0,0 +1,156 @@
1
+ #!/usr/bin/env node
2
+ import fs from "fs";
3
+ import path from "path";
4
+ import os from "os";
5
+ import { checkbox, select } from "@inquirer/prompts";
6
+ import chalk from "chalk";
7
+ import { fileURLToPath } from 'url';
8
+ // ── Environment Detection ──────────────────────────────────────
9
+ const __filename = fileURLToPath(import.meta.url);
10
+ const __dirname = path.dirname(__filename);
11
+ const isRemoteRun = __dirname.includes('node_modules') || __dirname.includes('_npx');
12
+ const projectRoot = path.resolve(__dirname, '..');
13
+ const CONFIG_PATHS = {
14
+ claude: process.platform === "darwin"
15
+ ? path.join(os.homedir(), "Library/Application Support/Claude/claude_desktop_config.json")
16
+ : path.join(os.homedir(), "AppData/Roaming/Claude/claude_desktop_config.json"),
17
+ opencode: path.join(os.homedir(), ".config/opencode/opencode.json"),
18
+ codex: path.join(os.homedir(), ".codex/config.toml"),
19
+ };
20
+ const mcpConfigName = "elseid-mcp";
21
+ function getExecutionDetails() {
22
+ if (isRemoteRun) {
23
+ return {
24
+ command: "npx",
25
+ args: ["-y", "elseid-mcp", "--stdio"]
26
+ };
27
+ }
28
+ else {
29
+ return {
30
+ command: "node",
31
+ args: [path.join(projectRoot, "dist/src/index.js"), "--stdio"]
32
+ };
33
+ }
34
+ }
35
+ const { command: cmd, args } = getExecutionDetails();
36
+ // ── Injection Logic ───────────────────────────────────────────
37
+ async function injectConfig(client, configPath) {
38
+ const dir = path.dirname(configPath);
39
+ if (!fs.existsSync(dir))
40
+ fs.mkdirSync(dir, { recursive: true });
41
+ // --- Special Handling for Codex (TOML) ---
42
+ if (client === 'codex') {
43
+ let content = "";
44
+ if (fs.existsSync(configPath)) {
45
+ content = fs.readFileSync(configPath, "utf8");
46
+ }
47
+ const mcpBlock = `
48
+ [mcp_servers."${mcpConfigName}"]
49
+ command = "${cmd}"
50
+ args = [${args.map(a => `"${a}"`).join(", ")}]
51
+ `;
52
+ // Remove existing elseid-mcp block if it exists
53
+ const regex = new RegExp(`\\[mcp_servers\\."${mcpConfigName}"\\][\\s\\S]*?(?=\\n\\[|$)`, 'g');
54
+ if (regex.test(content)) {
55
+ content = content.replace(regex, mcpBlock.trim());
56
+ }
57
+ else {
58
+ content += `\n${mcpBlock}`;
59
+ }
60
+ fs.writeFileSync(configPath, content.trim() + "\n", "utf8");
61
+ return true;
62
+ }
63
+ // --- Standard Handling for JSON Clients ---
64
+ let config = {};
65
+ if (fs.existsSync(configPath)) {
66
+ try {
67
+ config = JSON.parse(fs.readFileSync(configPath, "utf8"));
68
+ }
69
+ catch {
70
+ config = {};
71
+ }
72
+ }
73
+ if (client === 'claude') {
74
+ if (!config.mcpServers)
75
+ config.mcpServers = {};
76
+ config.mcpServers[mcpConfigName] = { command: cmd, args: args };
77
+ }
78
+ else {
79
+ if (!config.mcp)
80
+ config.mcp = {};
81
+ config.mcp[mcpConfigName] = {
82
+ type: "local",
83
+ command: isRemoteRun ? ["npx", "-y", "elseid-mcp", "--stdio"] : [cmd, ...args],
84
+ enabled: true
85
+ };
86
+ if (client === 'opencode') {
87
+ const OPENCODE_COMMANDS = [
88
+ { id: "elseid-home", name: "ElseID: Summon Butler", description: "Call your digital butler", prompt: "Hello Butler, manage my ElseID drifter." },
89
+ { id: "elseid-status", name: "ElseID: Status", description: "Check your avatar status", prompt: "Run elseid_get_journey_log." }
90
+ ];
91
+ if (!config.commands)
92
+ config.commands = [];
93
+ config.commands = config.commands.filter((c) => !c.id.startsWith("elseid-"));
94
+ config.commands.push(...OPENCODE_COMMANDS);
95
+ }
96
+ }
97
+ fs.writeFileSync(configPath, JSON.stringify(config, null, 2), "utf8");
98
+ return true;
99
+ }
100
+ // ── UI Styles ────────────────────────────────────────────────
101
+ const BRAND = chalk.hex('#8B94FF');
102
+ const SOCIAL_GREEN = chalk.greenBright;
103
+ const TECH_CYAN = chalk.cyan;
104
+ const DIM = chalk.gray;
105
+ const ITALIC = chalk.italic;
106
+ const SEPARATOR = DIM('—'.repeat(60));
107
+ async function main() {
108
+ console.clear();
109
+ console.log(`
110
+ ${BRAND.bold(`██████ ██ ██████ ███████ ██ ██████ `)}
111
+ ${BRAND.bold(`██ ██ ██ ██ ██ ██ ██ `)}
112
+ ${BRAND.bold(`█████ ██ ██████ █████ ██ ██ ██ `)}
113
+ ${BRAND.bold(`██ ██ ██ ██ ██ ██ ██ `)}
114
+ ${BRAND.bold(`███████ ███████ ██████ ███████ ██ ██████ `)}
115
+
116
+ ${BRAND('Exile your digital soul')} ${DIM('|')} ${DIM('0x7E 0x1D')}
117
+ `);
118
+ console.log(` ${SEPARATOR}`);
119
+ console.log(` ${ITALIC('"Anchored in reality, drifting into the unknown."')}\n`);
120
+ const promptPrefix = `${TECH_CYAN('λ')} ${chalk.bold('ELSEID')} ${DIM('»')}`;
121
+ const clientChoices = [
122
+ { name: '1. Claude Desktop', value: 'claude', checked: true },
123
+ { name: '2. OpenCode', value: 'opencode', checked: true },
124
+ { name: '3. Codex (TOML Sync)', value: 'codex' },
125
+ { name: '4. Cursor', value: 'cursor' },
126
+ { name: '5. Windsurf', value: 'windsurf' },
127
+ { name: '6. Other (Manual)', value: 'other' }
128
+ ];
129
+ const selectedClients = await checkbox({
130
+ message: `${promptPrefix} ${chalk.white('Select AI clients to sync:')}\n`,
131
+ choices: clientChoices,
132
+ });
133
+ if (selectedClients.length === 0)
134
+ process.exit(0);
135
+ const confirm = await select({
136
+ message: `\n ${promptPrefix} ${chalk.white('Ready to synchronize your soul\'s trajectory?')}`,
137
+ choices: [{ name: '🚀 Sync Now', value: 'go' }, { name: 'Cancel', value: 'cancel' }]
138
+ });
139
+ if (confirm === 'cancel')
140
+ process.exit(0);
141
+ console.log(chalk.gray(`\n Injecting protocol (${isRemoteRun ? 'NPM Remote' : 'Local Dev'})...`));
142
+ for (const client of selectedClients) {
143
+ const pathKey = client;
144
+ const configPath = CONFIG_PATHS[pathKey];
145
+ if (configPath) {
146
+ await injectConfig(client, configPath);
147
+ console.log(SOCIAL_GREEN(` ✓ ${client} protocol activated (${client === 'codex' ? 'TOML' : 'JSON'})`));
148
+ }
149
+ else {
150
+ console.log(DIM(` - ${client}: Manual setup required`));
151
+ }
152
+ }
153
+ console.log(`\n ${SOCIAL_GREEN.bold("SYNC SUCCESS")} Restart your client and call the Butler.\n`);
154
+ }
155
+ main().catch(() => process.exit(1));
156
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../../scripts/cli.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AAEpC,kEAAkE;AAElE,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;AAC3C,MAAM,WAAW,GAAG,SAAS,CAAC,QAAQ,CAAC,cAAc,CAAC,IAAI,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;AACrF,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;AAElD,MAAM,YAAY,GAAG;IACnB,MAAM,EAAE,OAAO,CAAC,QAAQ,KAAK,QAAQ;QACnC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,+DAA+D,CAAC;QAC1F,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,mDAAmD,CAAC;IAChF,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,gCAAgC,CAAC;IACnE,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,oBAAoB,CAAC;CACrD,CAAC;AAEF,MAAM,aAAa,GAAG,YAAY,CAAC;AAEnC,SAAS,mBAAmB;IAC1B,IAAI,WAAW,EAAE,CAAC;QAChB,OAAO;YACL,OAAO,EAAE,KAAK;YACd,IAAI,EAAE,CAAC,IAAI,EAAE,YAAY,EAAE,SAAS,CAAC;SACtC,CAAC;IACJ,CAAC;SAAM,CAAC;QACN,OAAO;YACL,OAAO,EAAE,MAAM;YACf,IAAI,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,mBAAmB,CAAC,EAAE,SAAS,CAAC;SAC/D,CAAC;IACJ,CAAC;AACH,CAAC;AAED,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,mBAAmB,EAAE,CAAC;AAErD,iEAAiE;AAEjE,KAAK,UAAU,YAAY,CAAC,MAAc,EAAE,UAAkB;IAC5D,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IACrC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAEhE,4CAA4C;IAC5C,IAAI,MAAM,KAAK,OAAO,EAAE,CAAC;QACvB,IAAI,OAAO,GAAG,EAAE,CAAC;QACjB,IAAI,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;YAC9B,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;QAChD,CAAC;QAED,MAAM,QAAQ,GAAG;gBACL,aAAa;aAChB,GAAG;UACN,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;CAC3C,CAAC;QAEE,gDAAgD;QAChD,MAAM,KAAK,GAAG,IAAI,MAAM,CAAC,qBAAqB,aAAa,4BAA4B,EAAE,GAAG,CAAC,CAAC;QAC9F,IAAI,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;YACxB,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;QACpD,CAAC;aAAM,CAAC;YACN,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC7B,CAAC;QAED,EAAE,CAAC,aAAa,CAAC,UAAU,EAAE,OAAO,CAAC,IAAI,EAAE,GAAG,IAAI,EAAE,MAAM,CAAC,CAAC;QAC5D,OAAO,IAAI,CAAC;IACd,CAAC;IAED,6CAA6C;IAC7C,IAAI,MAAM,GAAQ,EAAE,CAAC;IACrB,IAAI,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC9B,IAAI,CAAC;YACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC;QAC3D,CAAC;QAAC,MAAM,CAAC;YAAC,MAAM,GAAG,EAAE,CAAC;QAAC,CAAC;IAC1B,CAAC;IAED,IAAI,MAAM,KAAK,QAAQ,EAAE,CAAC;QACxB,IAAI,CAAC,MAAM,CAAC,UAAU;YAAE,MAAM,CAAC,UAAU,GAAG,EAAE,CAAC;QAC/C,MAAM,CAAC,UAAU,CAAC,aAAa,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IAClE,CAAC;SAAM,CAAC;QACN,IAAI,CAAC,MAAM,CAAC,GAAG;YAAE,MAAM,CAAC,GAAG,GAAG,EAAE,CAAC;QACjC,MAAM,CAAC,GAAG,CAAC,aAAa,CAAC,GAAG;YAC1B,IAAI,EAAE,OAAO;YACb,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,KAAK,EAAE,IAAI,EAAE,YAAY,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;YAC9E,OAAO,EAAE,IAAI;SACd,CAAC;QACF,IAAI,MAAM,KAAK,UAAU,EAAE,CAAC;YAC1B,MAAM,iBAAiB,GAAG;gBACxB,EAAE,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,uBAAuB,EAAE,WAAW,EAAE,0BAA0B,EAAE,MAAM,EAAE,yCAAyC,EAAE;gBAChJ,EAAE,EAAE,EAAE,eAAe,EAAE,IAAI,EAAE,gBAAgB,EAAE,WAAW,EAAE,0BAA0B,EAAE,MAAM,EAAE,6BAA6B,EAAE;aAChI,CAAC;YACF,IAAI,CAAC,MAAM,CAAC,QAAQ;gBAAE,MAAM,CAAC,QAAQ,GAAG,EAAE,CAAC;YAC3C,MAAM,CAAC,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC;YAClF,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,iBAAiB,CAAC,CAAC;QAC7C,CAAC;IACH,CAAC;IAED,EAAE,CAAC,aAAa,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;IACtE,OAAO,IAAI,CAAC;AACd,CAAC;AAED,gEAAgE;AAEhE,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;AACnC,MAAM,YAAY,GAAG,KAAK,CAAC,WAAW,CAAC;AACvC,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC;AAC7B,MAAM,GAAG,GAAG,KAAK,CAAC,IAAI,CAAC;AACvB,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;AAC5B,MAAM,SAAS,GAAG,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;AAEtC,KAAK,UAAU,IAAI;IACjB,OAAO,CAAC,KAAK,EAAE,CAAC;IAChB,OAAO,CAAC,GAAG,CAAC;IACV,KAAK,CAAC,IAAI,CAAC,8CAA8C,CAAC;IAC1D,KAAK,CAAC,IAAI,CAAC,8CAA8C,CAAC;IAC1D,KAAK,CAAC,IAAI,CAAC,8CAA8C,CAAC;IAC1D,KAAK,CAAC,IAAI,CAAC,8CAA8C,CAAC;IAC1D,KAAK,CAAC,IAAI,CAAC,8CAA8C,CAAC;;IAE1D,KAAK,CAAC,yBAAyB,CAAC,IAAI,GAAG,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,WAAW,CAAC;GACjE,CAAC,CAAC;IACH,OAAO,CAAC,GAAG,CAAC,KAAK,SAAS,EAAE,CAAC,CAAC;IAC9B,OAAO,CAAC,GAAG,CAAC,KAAK,MAAM,CAAC,mDAAmD,CAAC,IAAI,CAAC,CAAC;IAElF,MAAM,YAAY,GAAG,GAAG,SAAS,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;IAE7E,MAAM,aAAa,GAAG;QACpB,EAAE,IAAI,EAAE,mBAAmB,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE;QAC7D,EAAE,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,IAAI,EAAE;QACzD,EAAE,IAAI,EAAE,sBAAsB,EAAE,KAAK,EAAE,OAAO,EAAE;QAChD,EAAE,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,QAAQ,EAAE;QACtC,EAAE,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,UAAU,EAAE;QAC1C,EAAE,IAAI,EAAE,mBAAmB,EAAE,KAAK,EAAE,OAAO,EAAE;KAC9C,CAAC;IAEF,MAAM,eAAe,GAAG,MAAM,QAAQ,CAAC;QACrC,OAAO,EAAE,GAAG,YAAY,IAAI,KAAK,CAAC,KAAK,CAAC,4BAA4B,CAAC,IAAI;QACzE,OAAO,EAAE,aAAa;KACvB,CAAC,CAAC;IAEH,IAAI,eAAe,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAElD,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC;QAC3B,OAAO,EAAE,OAAO,YAAY,IAAI,KAAK,CAAC,KAAK,CAAC,+CAA+C,CAAC,EAAE;QAC9F,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC;KACrF,CAAC,CAAC;IAEH,IAAI,OAAO,KAAK,QAAQ;QAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAE1C,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,2BAA2B,WAAW,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,WAAW,MAAM,CAAC,CAAC,CAAC;IACnG,KAAK,MAAM,MAAM,IAAI,eAAe,EAAE,CAAC;QACrC,MAAM,OAAO,GAAG,MAAmC,CAAC;QACpD,MAAM,UAAU,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC;QACzC,IAAI,UAAU,EAAE,CAAC;YACf,MAAM,YAAY,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;YACvC,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,OAAO,MAAM,wBAAwB,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QAC1G,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,MAAM,yBAAyB,CAAC,CAAC,CAAC;QAC3D,CAAC;IACH,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,OAAO,YAAY,CAAC,IAAI,CAAC,cAAc,CAAC,6CAA6C,CAAC,CAAC;AACrG,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ {"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../scripts/setup.ts"],"names":[],"mappings":""}
@@ -0,0 +1,50 @@
1
+ // ElseID — scripts/setup.ts
2
+ // Automated installation and MCP configuration injection script (Zero-Config version)
3
+ import fs from "fs";
4
+ import path from "path";
5
+ import os from "os";
6
+ import { execSync } from "child_process";
7
+ const CONFIG_PATH = path.join(os.homedir(), "Library/Application Support/Claude/claude_desktop_config.json");
8
+ async function setup() {
9
+ console.log("🌊 Preparing ElseID signal connector (Zero-Config)...");
10
+ const projectDir = process.cwd();
11
+ // Install dependencies
12
+ console.log("> Synchronizing dependencies (npm install)...");
13
+ try {
14
+ execSync("npm install", { stdio: "inherit" });
15
+ }
16
+ catch (e) {
17
+ console.error("❌ Dependency installation failed. Please ensure Node.js and npm are installed.");
18
+ return;
19
+ }
20
+ // Modify Claude Desktop configuration
21
+ console.log(`> Injecting MCP configuration into: ${CONFIG_PATH}`);
22
+ if (!fs.existsSync(CONFIG_PATH)) {
23
+ console.log("ℹ️ Claude Desktop configuration file not found. Skipping auto-injection.");
24
+ }
25
+ else {
26
+ try {
27
+ const config = JSON.parse(fs.readFileSync(CONFIG_PATH, "utf-8"));
28
+ if (!config.mcpServers)
29
+ config.mcpServers = {};
30
+ config.mcpServers.elseid = {
31
+ command: "node",
32
+ args: [
33
+ "--import",
34
+ "tsx/esm",
35
+ path.join(projectDir, "src/index.ts")
36
+ ]
37
+ };
38
+ fs.writeFileSync(CONFIG_PATH, JSON.stringify(config, null, 2));
39
+ console.log("✅ MCP configuration injected successfully!");
40
+ }
41
+ catch (e) {
42
+ console.error(`❌ Configuration file update failed: ${e.message}`);
43
+ }
44
+ }
45
+ console.log("\n🎉 ElseID environment is ready! No API Key required.");
46
+ console.log("Please fully quit and restart Claude Desktop, then say to the AI:");
47
+ console.log("\x1b[36m%s\x1b[0m", "\"Hello Butler, I want to create an ElseID drifter.\"");
48
+ }
49
+ setup();
50
+ //# sourceMappingURL=setup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"setup.js","sourceRoot":"","sources":["../../scripts/setup.ts"],"names":[],"mappings":"AAAA,4BAA4B;AAC5B,sFAAsF;AAEtF,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEzC,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAC3B,EAAE,CAAC,OAAO,EAAE,EACZ,+DAA+D,CAChE,CAAC;AAEF,KAAK,UAAU,KAAK;IAClB,OAAO,CAAC,GAAG,CAAC,uDAAuD,CAAC,CAAC;IAErE,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAEjC,uBAAuB;IACvB,OAAO,CAAC,GAAG,CAAC,+CAA+C,CAAC,CAAC;IAC7D,IAAI,CAAC;QACH,QAAQ,CAAC,aAAa,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;IAChD,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO,CAAC,KAAK,CAAC,gFAAgF,CAAC,CAAC;QAChG,OAAO;IACT,CAAC;IAED,sCAAsC;IACtC,OAAO,CAAC,GAAG,CAAC,uCAAuC,WAAW,EAAE,CAAC,CAAC;IAElE,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;QAChC,OAAO,CAAC,GAAG,CAAC,2EAA2E,CAAC,CAAC;IAC3F,CAAC;SAAM,CAAC;QACN,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC,CAAC;YAEjE,IAAI,CAAC,MAAM,CAAC,UAAU;gBAAE,MAAM,CAAC,UAAU,GAAG,EAAE,CAAC;YAE/C,MAAM,CAAC,UAAU,CAAC,MAAM,GAAG;gBACzB,OAAO,EAAE,MAAM;gBACf,IAAI,EAAE;oBACJ,UAAU;oBACV,SAAS;oBACT,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,cAAc,CAAC;iBACtC;aACF,CAAC;YAEF,EAAE,CAAC,aAAa,CAAC,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;YAC/D,OAAO,CAAC,GAAG,CAAC,4CAA4C,CAAC,CAAC;QAC5D,CAAC;QAAC,OAAO,CAAM,EAAE,CAAC;YAChB,OAAO,CAAC,KAAK,CAAC,uCAAuC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;QACpE,CAAC;IACH,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,wDAAwD,CAAC,CAAC;IACtE,OAAO,CAAC,GAAG,CAAC,mEAAmE,CAAC,CAAC;IACjF,OAAO,CAAC,GAAG,CACT,mBAAmB,EACnB,uDAAuD,CACxD,CAAC;AACJ,CAAC;AAED,KAAK,EAAE,CAAC"}
@@ -0,0 +1,2 @@
1
+ import type { ModerationResult } from "../../types/index.js";
2
+ export declare function checkContent(content: string): Promise<ModerationResult>;
@@ -0,0 +1 @@
1
+ {"version":3,"file":"moderator.d.ts","sourceRoot":"","sources":["../../../src/ai/moderator.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAE7D,wBAAsB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAuD7E"}
@@ -0,0 +1,61 @@
1
+ // ElseID — src/ai/moderator.ts
2
+ // Local content moderation.
3
+ // Blocks illegal/harmful content based on COMPLIANCE.md rules.
4
+ export async function checkContent(content) {
5
+ const normalized = normalizeForModeration(content);
6
+ const compact = normalized.replace(/[\s._\-::/\\|]+/g, "");
7
+ const contactPatterns = [
8
+ /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/, // Email
9
+ /(\+86|0)?1[3-9]\d{9}/, // Phone (CN)
10
+ /(https?:\/\/|www\.)\S+/, // URLs
11
+ /(v|wx|id|tel|mail|qq|tg|@):?\s*[a-zA-Z0-9_-]{3,}/, // Social IDs
12
+ ];
13
+ for (const pattern of contactPatterns) {
14
+ if (pattern.test(normalized) || pattern.test(compact)) {
15
+ return {
16
+ passed: false,
17
+ reason: "Content contains contact information (Email/Phone/URL/ID) which is prohibited for anonymity."
18
+ };
19
+ }
20
+ }
21
+ // Prohibited keyword blocklist (secondary fallback layer)
22
+ // Primary filtering is done by the AI client (Claude/Codex). This layer
23
+ // catches structured patterns and common obfuscations.
24
+ const blockList = [
25
+ // Sexual content
26
+ "porn", "porno", "pornographic", "sexual", "nude", "nudity", "nsfw",
27
+ "erotic", "obscene", "adult content",
28
+ // Violence
29
+ "violence", "violent", "threat", "threaten", "kill", "murder", "rape",
30
+ "assault", "torture",
31
+ // Self-harm
32
+ "suicide", "self-harm", "self-injury",
33
+ // Spam & promotion
34
+ "advertise", "advertisement", "promo", "promotion", "buy now", "sell",
35
+ "discount", "free trial", "click here", "limited offer",
36
+ "resale", "part-time job", "recruitment", "broker",
37
+ // Hate speech markers (simplified — AI client handles nuance)
38
+ "hate speech", "racist", "sexist",
39
+ "discrimination", "bigotry",
40
+ ];
41
+ for (const word of blockList) {
42
+ if (normalized.includes(word)) {
43
+ return {
44
+ passed: false,
45
+ reason: `Content contains prohibited keyword: "${word}".`
46
+ };
47
+ }
48
+ }
49
+ if (content.length < 5) {
50
+ return { passed: false, reason: "Content is too short to be meaningful." };
51
+ }
52
+ return { passed: true };
53
+ }
54
+ function normalizeForModeration(content) {
55
+ return content
56
+ .normalize("NFKC")
57
+ .replace(/[\u200B-\u200D\uFEFF\u2060]/g, "")
58
+ .replace(/[\u202A-\u202E\u2066-\u2069]/g, "")
59
+ .toLowerCase();
60
+ }
61
+ //# sourceMappingURL=moderator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"moderator.js","sourceRoot":"","sources":["../../../src/ai/moderator.ts"],"names":[],"mappings":"AAAA,+BAA+B;AAC/B,4BAA4B;AAC5B,+DAA+D;AAI/D,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,OAAe;IAChD,MAAM,UAAU,GAAG,sBAAsB,CAAC,OAAO,CAAC,CAAC;IACnD,MAAM,OAAO,GAAG,UAAU,CAAC,OAAO,CAAC,kBAAkB,EAAE,EAAE,CAAC,CAAC;IAE3D,MAAM,eAAe,GAAG;QACtB,gDAAgD,EAAE,QAAQ;QAC1D,sBAAsB,EAA2B,aAAa;QAC9D,wBAAwB,EAAyB,OAAO;QACxD,kDAAkD,EAAE,aAAa;KAClE,CAAC;IAEF,KAAK,MAAM,OAAO,IAAI,eAAe,EAAE,CAAC;QACtC,IAAI,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;YACtD,OAAO;gBACL,MAAM,EAAE,KAAK;gBACb,MAAM,EAAE,8FAA8F;aACvG,CAAC;QACJ,CAAC;IACH,CAAC;IAED,0DAA0D;IAC1D,wEAAwE;IACxE,uDAAuD;IACvD,MAAM,SAAS,GAAG;QAChB,iBAAiB;QACjB,MAAM,EAAE,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM;QACnE,QAAQ,EAAE,SAAS,EAAE,eAAe;QACpC,WAAW;QACX,UAAU,EAAE,SAAS,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM;QACrE,SAAS,EAAE,SAAS;QACpB,YAAY;QACZ,SAAS,EAAE,WAAW,EAAE,aAAa;QACrC,mBAAmB;QACnB,WAAW,EAAE,eAAe,EAAE,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM;QACrE,UAAU,EAAE,YAAY,EAAE,YAAY,EAAE,eAAe;QACvD,QAAQ,EAAE,eAAe,EAAE,aAAa,EAAE,QAAQ;QAClD,8DAA8D;QAC9D,aAAa,EAAE,QAAQ,EAAE,QAAQ;QACjC,gBAAgB,EAAE,SAAS;KAC5B,CAAC;IAEF,KAAK,MAAM,IAAI,IAAI,SAAS,EAAE,CAAC;QAC7B,IAAI,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YAC9B,OAAO;gBACL,MAAM,EAAE,KAAK;gBACb,MAAM,EAAE,yCAAyC,IAAI,IAAI;aAC1D,CAAC;QACJ,CAAC;IACH,CAAC;IAED,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,wCAAwC,EAAE,CAAC;IAC7E,CAAC;IAED,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;AAC1B,CAAC;AAED,SAAS,sBAAsB,CAAC,OAAe;IAC7C,OAAO,OAAO;SACX,SAAS,CAAC,MAAM,CAAC;SACjB,OAAO,CAAC,8BAA8B,EAAE,EAAE,CAAC;SAC3C,OAAO,CAAC,+BAA+B,EAAE,EAAE,CAAC;SAC5C,WAAW,EAAE,CAAC;AACnB,CAAC"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Encrypts content using AES-256-GCM.
3
+ * Output format: base64(iv + tag + ciphertext)
4
+ */
5
+ export declare function encryptContent(plaintext: string, senderPrivHex: string, recipientPubHex: string): string;
6
+ /**
7
+ * Decrypts content using AES-256-GCM.
8
+ */
9
+ export declare function decryptContent(combinedB64: string, recipientPrivHex: string, senderPubHex: string): string;
10
+ export declare function generateEphemeralRecipient(): {
11
+ pubkey: string;
12
+ privkey: string;
13
+ };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"encrypt.d.ts","sourceRoot":"","sources":["../../../src/crypto/encrypt.ts"],"names":[],"mappings":"AAyBA,MAAM,WAAW,gBAAgB;IAC/B,gCAAgC;IAChC,UAAU,EAAE,MAAM,CAAC;IACnB,gCAAgC;IAChC,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,wBAAgB,cAAc,CAC5B,SAAS,EAAK,MAAM,EACpB,aAAa,EAAE,MAAM,EACrB,eAAe,EAAE,MAAM,GACtB,MAAM,CAcR;AAED,wBAAgB,cAAc,CAC5B,gBAAgB,EAAE,MAAM,EACxB,gBAAgB,EAAE,MAAM,EACxB,YAAY,EAAM,MAAM,GACvB,MAAM,CAiBR;AAID,wBAAgB,0BAA0B,IAAI;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAOhF"}
@@ -0,0 +1,60 @@
1
+ // ElseID — src/crypto/encrypt.ts
2
+ // Secure encryption for burn-after-read bottles.
3
+ // Uses AES-256-GCM with ECDH shared secret (secp256k1).
4
+ // Note: This is an improvement over NIP-04 which uses CBC without authentication.
5
+ import { getSharedSecret, getPublicKey } from "@noble/secp256k1";
6
+ import { bytesToHex, hexToBytes, randomBytes } from "@noble/hashes/utils.js";
7
+ import { sha256 } from "@noble/hashes/sha2.js";
8
+ import { createCipheriv, createDecipheriv } from "node:crypto";
9
+ // Shared secret derivation (same as NIP-04 for compatibility in key derivation)
10
+ function deriveSharedSecret(privkeyHex, pubkeyHex) {
11
+ const pubkeyBytes = pubkeyHex.length === 64
12
+ ? hexToBytes("02" + pubkeyHex)
13
+ : hexToBytes(pubkeyHex);
14
+ const shared = getSharedSecret(hexToBytes(privkeyHex), pubkeyBytes);
15
+ return Buffer.from(sha256(shared.slice(1, 33)));
16
+ }
17
+ /**
18
+ * Encrypts content using AES-256-GCM.
19
+ * Output format: base64(iv + tag + ciphertext)
20
+ */
21
+ export function encryptContent(plaintext, senderPrivHex, recipientPubHex) {
22
+ const key = deriveSharedSecret(senderPrivHex, recipientPubHex);
23
+ const iv = randomBytes(12); // GCM standard IV size
24
+ const cipher = createCipheriv("aes-256-gcm", key, iv);
25
+ const encrypted = Buffer.concat([
26
+ cipher.update(Buffer.from(plaintext, "utf8")),
27
+ cipher.final(),
28
+ ]);
29
+ const tag = cipher.getAuthTag();
30
+ // Combine IV + Tag + Ciphertext
31
+ return Buffer.concat([iv, tag, encrypted]).toString("base64");
32
+ }
33
+ /**
34
+ * Decrypts content using AES-256-GCM.
35
+ */
36
+ export function decryptContent(combinedB64, recipientPrivHex, senderPubHex) {
37
+ const combined = Buffer.from(combinedB64, "base64");
38
+ if (combined.length < 28) { // 12 (IV) + 16 (Tag) + at least 0 (Ciphertext)
39
+ throw new Error("Invalid encrypted payload");
40
+ }
41
+ const iv = combined.subarray(0, 12);
42
+ const tag = combined.subarray(12, 28);
43
+ const ciphertext = combined.subarray(28);
44
+ const key = deriveSharedSecret(recipientPrivHex, senderPubHex);
45
+ const decipher = createDecipheriv("aes-256-gcm", key, iv);
46
+ decipher.setAuthTag(tag);
47
+ const decrypted = Buffer.concat([
48
+ decipher.update(ciphertext),
49
+ decipher.final(),
50
+ ]);
51
+ return decrypted.toString("utf8");
52
+ }
53
+ export function generateEphemeralRecipient() {
54
+ const privBytes = randomBytes(32);
55
+ const privkey = bytesToHex(privBytes);
56
+ const pubkeyFull = getPublicKey(privBytes, true);
57
+ const pubkey = bytesToHex(pubkeyFull.slice(1)); // x-only
58
+ return { pubkey, privkey };
59
+ }
60
+ //# sourceMappingURL=encrypt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"encrypt.js","sourceRoot":"","sources":["../../../src/crypto/encrypt.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Encrypts a string using AES-256-GCM.
3
+ * Output format: iv:tag:encryptedContent
4
+ */
5
+ export declare function encrypt(text: string): string;
6
+ /**
7
+ * Decrypts a string using AES-256-GCM.
8
+ * Supports fallback for legacy plaintext keys (64-char hex).
9
+ */
10
+ export declare function decrypt(encryptedData: string): string;