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.
- package/LICENSE +662 -0
- package/README.md +138 -0
- package/dist/config/relays.d.ts +13 -0
- package/dist/config/relays.d.ts.map +1 -0
- package/dist/config/relays.js +51 -0
- package/dist/config/relays.js.map +1 -0
- package/dist/scripts/cli.d.ts +2 -0
- package/dist/scripts/cli.d.ts.map +1 -0
- package/dist/scripts/cli.js +156 -0
- package/dist/scripts/cli.js.map +1 -0
- package/dist/scripts/setup.d.ts +1 -0
- package/dist/scripts/setup.d.ts.map +1 -0
- package/dist/scripts/setup.js +50 -0
- package/dist/scripts/setup.js.map +1 -0
- package/dist/src/ai/moderator.d.ts +2 -0
- package/dist/src/ai/moderator.d.ts.map +1 -0
- package/dist/src/ai/moderator.js +61 -0
- package/dist/src/ai/moderator.js.map +1 -0
- package/dist/src/crypto/encrypt.d.ts +13 -0
- package/dist/src/crypto/encrypt.d.ts.map +1 -0
- package/dist/src/crypto/encrypt.js +60 -0
- package/dist/src/crypto/encrypt.js.map +1 -0
- package/dist/src/crypto/encryption.d.ts +10 -0
- package/dist/src/crypto/encryption.js +69 -0
- package/dist/src/crypto/encryption.js.map +1 -0
- package/dist/src/crypto/keypair.d.ts +4 -0
- package/dist/src/crypto/keypair.d.ts.map +1 -0
- package/dist/src/crypto/keypair.js +86 -0
- package/dist/src/crypto/keypair.js.map +1 -0
- package/dist/src/evolution/backpack.d.ts +7 -0
- package/dist/src/evolution/backpack.d.ts.map +1 -0
- package/dist/src/evolution/backpack.js +15 -0
- package/dist/src/evolution/backpack.js.map +1 -0
- package/dist/src/evolution/skills.d.ts +7 -0
- package/dist/src/evolution/skills.d.ts.map +1 -0
- package/dist/src/evolution/skills.js +10 -0
- package/dist/src/evolution/skills.js.map +1 -0
- package/dist/src/evolution/synthesis.d.ts +11 -0
- package/dist/src/evolution/synthesis.d.ts.map +1 -0
- package/dist/src/evolution/synthesis.js +80 -0
- package/dist/src/evolution/synthesis.js.map +1 -0
- package/dist/src/index.d.ts +1 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +65 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/location/geo.d.ts +3 -0
- package/dist/src/location/geo.d.ts.map +1 -0
- package/dist/src/location/geo.js +35 -0
- package/dist/src/location/geo.js.map +1 -0
- package/dist/src/nostr/event_builder.d.ts +22 -0
- package/dist/src/nostr/event_builder.d.ts.map +1 -0
- package/dist/src/nostr/event_builder.js +65 -0
- package/dist/src/nostr/event_builder.js.map +1 -0
- package/dist/src/nostr/event_signer.d.ts +4 -0
- package/dist/src/nostr/event_signer.d.ts.map +1 -0
- package/dist/src/nostr/event_signer.js +38 -0
- package/dist/src/nostr/event_signer.js.map +1 -0
- package/dist/src/nostr/filter.d.ts +11 -0
- package/dist/src/nostr/filter.d.ts.map +1 -0
- package/dist/src/nostr/filter.js +23 -0
- package/dist/src/nostr/filter.js.map +1 -0
- package/dist/src/nostr/ws_pool.d.ts +15 -0
- package/dist/src/nostr/ws_pool.d.ts.map +1 -0
- package/dist/src/nostr/ws_pool.js +291 -0
- package/dist/src/nostr/ws_pool.js.map +1 -0
- package/dist/src/relay/broadcaster.d.ts +8 -0
- package/dist/src/relay/broadcaster.d.ts.map +1 -0
- package/dist/src/relay/broadcaster.js +85 -0
- package/dist/src/relay/broadcaster.js.map +1 -0
- package/dist/src/relay/health.d.ts +5 -0
- package/dist/src/relay/health.d.ts.map +1 -0
- package/dist/src/relay/health.js +118 -0
- package/dist/src/relay/health.js.map +1 -0
- package/dist/src/relay/selector.d.ts +4 -0
- package/dist/src/relay/selector.d.ts.map +1 -0
- package/dist/src/relay/selector.js +45 -0
- package/dist/src/relay/selector.js.map +1 -0
- package/dist/src/storage/db.d.ts +4 -0
- package/dist/src/storage/db.d.ts.map +1 -0
- package/dist/src/storage/db.js +195 -0
- package/dist/src/storage/db.js.map +1 -0
- package/dist/src/storage/drifters.d.ts +18 -0
- package/dist/src/storage/drifters.d.ts.map +1 -0
- package/dist/src/storage/drifters.js +172 -0
- package/dist/src/storage/drifters.js.map +1 -0
- package/dist/src/storage/encounters.d.ts +2 -0
- package/dist/src/storage/encounters.d.ts.map +1 -0
- package/dist/src/storage/encounters.js +24 -0
- package/dist/src/storage/encounters.js.map +1 -0
- package/dist/src/storage/identity.d.ts +6 -0
- package/dist/src/storage/identity.d.ts.map +1 -0
- package/dist/src/storage/identity.js +42 -0
- package/dist/src/storage/identity.js.map +1 -0
- package/dist/src/tools/abandon_drifter.d.ts +2 -0
- package/dist/src/tools/abandon_drifter.d.ts.map +1 -0
- package/dist/src/tools/abandon_drifter.js +45 -0
- package/dist/src/tools/abandon_drifter.js.map +1 -0
- package/dist/src/tools/create_drifter.d.ts +2 -0
- package/dist/src/tools/create_drifter.d.ts.map +1 -0
- package/dist/src/tools/create_drifter.js +98 -0
- package/dist/src/tools/create_drifter.js.map +1 -0
- package/dist/src/tools/evolve_drifter.d.ts +2 -0
- package/dist/src/tools/evolve_drifter.d.ts.map +1 -0
- package/dist/src/tools/evolve_drifter.js +45 -0
- package/dist/src/tools/evolve_drifter.js.map +1 -0
- package/dist/src/tools/feed_drifter.d.ts +2 -0
- package/dist/src/tools/feed_drifter.d.ts.map +1 -0
- package/dist/src/tools/feed_drifter.js +86 -0
- package/dist/src/tools/feed_drifter.js.map +1 -0
- package/dist/src/tools/find_nearby_drifter.d.ts +2 -0
- package/dist/src/tools/find_nearby_drifter.d.ts.map +1 -0
- package/dist/src/tools/find_nearby_drifter.js +70 -0
- package/dist/src/tools/find_nearby_drifter.js.map +1 -0
- package/dist/src/tools/get_journey_log.d.ts +2 -0
- package/dist/src/tools/get_journey_log.d.ts.map +1 -0
- package/dist/src/tools/get_journey_log.js +61 -0
- package/dist/src/tools/get_journey_log.js.map +1 -0
- package/dist/src/tools/get_my_encounters.d.ts +2 -0
- package/dist/src/tools/get_my_encounters.d.ts.map +1 -0
- package/dist/src/tools/get_my_encounters.js +23 -0
- package/dist/src/tools/get_my_encounters.js.map +1 -0
- package/dist/src/tools/list_past_memories.d.ts +2 -0
- package/dist/src/tools/list_past_memories.d.ts.map +1 -0
- package/dist/src/tools/list_past_memories.js +41 -0
- package/dist/src/tools/list_past_memories.js.map +1 -0
- package/dist/src/tools/recover_drifter.d.ts +2 -0
- package/dist/src/tools/recover_drifter.d.ts.map +1 -0
- package/dist/src/tools/recover_drifter.js +82 -0
- package/dist/src/tools/recover_drifter.js.map +1 -0
- package/dist/src/tools/relay_tools.d.ts +2 -0
- package/dist/src/tools/relay_tools.d.ts.map +1 -0
- package/dist/src/tools/relay_tools.js +72 -0
- package/dist/src/tools/relay_tools.js.map +1 -0
- package/dist/src/tools/set_host_name.d.ts +2 -0
- package/dist/src/tools/set_host_name.d.ts.map +1 -0
- package/dist/src/tools/set_host_name.js +23 -0
- package/dist/src/tools/set_host_name.js.map +1 -0
- package/dist/src/utils/errors.d.ts +4 -0
- package/dist/src/utils/errors.js +28 -0
- package/dist/src/utils/errors.js.map +1 -0
- package/dist/src/utils/redact.d.ts +1 -0
- package/dist/src/utils/redact.d.ts.map +1 -0
- package/dist/src/utils/redact.js +20 -0
- package/dist/src/utils/redact.js.map +1 -0
- package/dist/src/utils/text.d.ts +2 -0
- package/dist/src/utils/text.d.ts.map +1 -0
- package/dist/src/utils/text.js +15 -0
- package/dist/src/utils/text.js.map +1 -0
- package/dist/types/index.d.ts +97 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +7 -0
- package/dist/types/index.js.map +1 -0
- package/docs/system_prompt.md +159 -0
- package/package.json +52 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recover_drifter.js","sourceRoot":"","sources":["../../../src/tools/recover_drifter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"relay_tools.d.ts","sourceRoot":"","sources":["../../../src/tools/relay_tools.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,SAAS,EAAE,MAAiB,yCAAyC,CAAC;AAM/E,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,SAAS,QA6EnD"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
// ElseID — src/tools/relay_tools.ts
|
|
2
|
+
// MCP Tools: list_relays, check_relay_status, pick_relay
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
import { checkRelay, getCachedRelayInfo, checkAllRelays } from "../relay/health.js";
|
|
5
|
+
import { pickRelay } from "../relay/selector.js";
|
|
6
|
+
export function registerRelayTools(server) {
|
|
7
|
+
// list_relays
|
|
8
|
+
server.tool("list_relays", "List all known relays with their cached online status and latency. Triggers a background refresh if data is stale.", {}, async () => {
|
|
9
|
+
const relays = await getCachedRelayInfo();
|
|
10
|
+
if (relays.length === 0) {
|
|
11
|
+
// No cache yet — run a fresh check
|
|
12
|
+
const fresh = await checkAllRelays();
|
|
13
|
+
return { content: [{ type: "text", text: formatRelayList(fresh) }] };
|
|
14
|
+
}
|
|
15
|
+
return { content: [{ type: "text", text: formatRelayList(relays) }] };
|
|
16
|
+
});
|
|
17
|
+
// check_relay_status
|
|
18
|
+
server.tool("check_relay_status", "Perform a live health check on a specific Nostr relay and return its status.", { url: z.string().url().describe("WebSocket relay URL, e.g. wss://relay.damus.io") }, async ({ url }) => {
|
|
19
|
+
const info = await checkRelay(url);
|
|
20
|
+
return {
|
|
21
|
+
content: [{
|
|
22
|
+
type: "text",
|
|
23
|
+
text: [
|
|
24
|
+
`🔌 Relay: ${info.url}`,
|
|
25
|
+
` Status : ${info.online ? "🟢 Online" : "🔴 Offline"}`,
|
|
26
|
+
` Latency : ${info.latencyMs !== null ? `${info.latencyMs}ms` : "—"}`,
|
|
27
|
+
` Writable: ${info.writable ? "✅ Yes" : "❌ No"}`,
|
|
28
|
+
].join("\n"),
|
|
29
|
+
}],
|
|
30
|
+
};
|
|
31
|
+
});
|
|
32
|
+
// pick_relay
|
|
33
|
+
server.tool("pick_relay", "Let the system pick the best available relay for your next create_drifter call.", {}, async () => {
|
|
34
|
+
const url = await pickRelay();
|
|
35
|
+
return {
|
|
36
|
+
content: [{
|
|
37
|
+
type: "text",
|
|
38
|
+
text: `🎯 Best relay selected: ${url}\n\nYou can pass this as the relay parameter in create_drifter.`,
|
|
39
|
+
}],
|
|
40
|
+
};
|
|
41
|
+
});
|
|
42
|
+
// refresh_relays
|
|
43
|
+
server.tool("refresh_relays", "Run a fresh health check on ALL known relays and update the local cache.", {}, async () => {
|
|
44
|
+
const results = await checkAllRelays();
|
|
45
|
+
const online = results.filter((r) => r.online).length;
|
|
46
|
+
return {
|
|
47
|
+
content: [{
|
|
48
|
+
type: "text",
|
|
49
|
+
text: [
|
|
50
|
+
`✅ Relay check complete: ${online}/${results.length} online`,
|
|
51
|
+
``,
|
|
52
|
+
formatRelayList(results),
|
|
53
|
+
].join("\n"),
|
|
54
|
+
}],
|
|
55
|
+
};
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
// Formatting
|
|
59
|
+
function formatRelayList(relays) {
|
|
60
|
+
if (relays.length === 0)
|
|
61
|
+
return "No relay data available.";
|
|
62
|
+
const header = `📡 Relay Status (${relays.filter(r => r.online).length}/${relays.length} online)\n`;
|
|
63
|
+
const rows = relays.map((r, i) => {
|
|
64
|
+
const status = r.online ? "🟢" : "🔴";
|
|
65
|
+
const write = r.writable ? "✍️ " : "👁️ ";
|
|
66
|
+
const latency = r.latencyMs !== null ? `${r.latencyMs}ms`.padStart(6) : " — ";
|
|
67
|
+
const label = r.region ? `[${r.region}] Relay Station ${i + 1}` : `Relay Station ${i + 1}`;
|
|
68
|
+
return ` ${status} ${write} ${latency} ${label}`;
|
|
69
|
+
});
|
|
70
|
+
return header + rows.join("\n");
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=relay_tools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"relay_tools.js","sourceRoot":"","sources":["../../../src/tools/relay_tools.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"set_host_name.d.ts","sourceRoot":"","sources":["../../../src/tools/set_host_name.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAKpE,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,SAAS,QAqBpD"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { setHostName } from "../storage/identity.js";
|
|
3
|
+
import { sanitizeName } from "../utils/text.js";
|
|
4
|
+
import { sanitizeErrorMessage } from "../utils/errors.js";
|
|
5
|
+
export function registerSetHostName(server) {
|
|
6
|
+
server.tool("set_host_name", "Set the name of the user (Host) so that drifters know who is feeding them.", {
|
|
7
|
+
name: z.string().min(1).max(80).describe("The chosen name of the Host"),
|
|
8
|
+
}, async ({ name }) => {
|
|
9
|
+
try {
|
|
10
|
+
const safeName = sanitizeName(name, "Host");
|
|
11
|
+
await setHostName(safeName);
|
|
12
|
+
return {
|
|
13
|
+
content: [{ type: "text", text: `Host name successfully set to: ${safeName}. The cosmos will now remember you by this name.` }],
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
catch (err) {
|
|
17
|
+
return {
|
|
18
|
+
content: [{ type: "text", text: `Error: Could not set host name. ${sanitizeErrorMessage(err)}` }],
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=set_host_name.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"set_host_name.js","sourceRoot":"","sources":["../../../src/tools/set_host_name.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAE1D,MAAM,UAAU,mBAAmB,CAAC,MAAiB;IACnD,MAAM,CAAC,IAAI,CACT,eAAe,EACf,4EAA4E,EAC5E;QACE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,6BAA6B,CAAC;KACxE,EACD,KAAK,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE;QACjB,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;YAC5C,MAAM,WAAW,CAAC,QAAQ,CAAC,CAAC;YAC5B,OAAO;gBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,kCAAkC,QAAQ,kDAAkD,EAAE,CAAC;aAChI,CAAC;QACJ,CAAC;QAAC,OAAO,GAAQ,EAAE,CAAC;YAClB,OAAO;gBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,mCAAmC,oBAAoB,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;aAClG,CAAC;QACJ,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// ElseID — src/utils/errors.ts
|
|
2
|
+
// Error sanitization for user-facing MCP messages.
|
|
3
|
+
/**
|
|
4
|
+
* Sanitizes an error message to prevent leaking internal paths or sensitive details.
|
|
5
|
+
*/
|
|
6
|
+
export function sanitizeErrorMessage(err) {
|
|
7
|
+
if (!err)
|
|
8
|
+
return "An unknown error occurred.";
|
|
9
|
+
let msg = err instanceof Error ? err.message : String(err);
|
|
10
|
+
// Mask absolute paths
|
|
11
|
+
const homeDir = process.env.HOME || "";
|
|
12
|
+
if (homeDir) {
|
|
13
|
+
msg = msg.split(homeDir).join("~");
|
|
14
|
+
}
|
|
15
|
+
// Mask generic system paths (e.g., /Users/..., /home/..., C:\Users\...)
|
|
16
|
+
msg = msg.replace(/\/[a-zA-Z0-9._\-/]+/g, (m) => {
|
|
17
|
+
if (m.includes("node_modules") || m.includes(".elseid")) {
|
|
18
|
+
return "[INTERNAL_PATH]";
|
|
19
|
+
}
|
|
20
|
+
return m;
|
|
21
|
+
});
|
|
22
|
+
// Shorten overly long messages
|
|
23
|
+
if (msg.length > 200) {
|
|
24
|
+
msg = msg.substring(0, 197) + "...";
|
|
25
|
+
}
|
|
26
|
+
return msg;
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../../src/utils/errors.ts"],"names":[],"mappings":"AAAA,+BAA+B;AAC/B,mDAAmD;AAInD;;GAEG;AACH,MAAM,UAAU,oBAAoB,CAAC,GAAY;IAC/C,IAAI,CAAC,GAAG;QAAE,OAAO,4BAA4B,CAAC;IAE9C,IAAI,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAE3D,sBAAsB;IACtB,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC;IACvC,IAAI,OAAO,EAAE,CAAC;QACZ,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACrC,CAAC;IAED,wEAAwE;IACxE,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,sBAAsB,EAAE,CAAC,CAAC,EAAE,EAAE;QAC9C,IAAI,CAAC,CAAC,QAAQ,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;YACxD,OAAO,iBAAiB,CAAC;QAC3B,CAAC;QACD,OAAO,CAAC,CAAC;IACX,CAAC,CAAC,CAAC;IAEH,+BAA+B;IAC/B,IAAI,GAAG,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC;QACrB,GAAG,GAAG,GAAG,CAAC,SAAS,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,KAAK,CAAC;IACtC,CAAC;IAED,OAAO,GAAG,CAAC;AACb,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function redactSecrets(value: unknown): string;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"redact.d.ts","sourceRoot":"","sources":["../../../src/utils/redact.ts"],"names":[],"mappings":"AAKA,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAWpD"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
const SECRET_PATTERNS = [
|
|
2
|
+
/(privkey|private[_-]?key|secret)(["'\s:=]+)([^"'\s,}]+)/gi,
|
|
3
|
+
];
|
|
4
|
+
export function redactSecrets(value) {
|
|
5
|
+
const text = value instanceof Error
|
|
6
|
+
? `${value.name}: ${value.message}\n${value.stack ?? ""}`
|
|
7
|
+
: safeStringify(value);
|
|
8
|
+
return SECRET_PATTERNS.reduce((acc, pattern) => {
|
|
9
|
+
return acc.replace(pattern, "$1$2[REDACTED]");
|
|
10
|
+
}, text);
|
|
11
|
+
}
|
|
12
|
+
function safeStringify(value) {
|
|
13
|
+
try {
|
|
14
|
+
return typeof value === "string" ? value : JSON.stringify(value);
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
return String(value);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=redact.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"redact.js","sourceRoot":"","sources":["../../../src/utils/redact.ts"],"names":[],"mappings":"AAAA,MAAM,eAAe,GAAG;IACtB,2DAA2D;CAC5D,CAAC;AAEF,MAAM,UAAU,aAAa,CAAC,KAAc;IAC1C,MAAM,IAAI,GAAG,KAAK,YAAY,KAAK;QACjC,CAAC,CAAC,GAAG,KAAK,CAAC,IAAI,KAAK,KAAK,CAAC,OAAO,KAAK,KAAK,CAAC,KAAK,IAAI,EAAE,EAAE;QACzD,CAAC,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;IAEzB,OAAO,eAAe,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,OAAO,EAAE,EAAE;QAC7C,OAAO,GAAG,CAAC,OAAO,CAAC,OAAO,EAAE,gBAAgB,CAAC,CAAC;IAChD,CAAC,EAAE,IAAI,CAAC,CAAC;AACX,CAAC;AAED,SAAS,aAAa,CAAC,KAAc;IACnC,IAAI,CAAC;QACH,OAAO,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IACnE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;IACvB,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"text.d.ts","sourceRoot":"","sources":["../../../src/utils/text.ts"],"names":[],"mappings":"AAGA,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAAE,SAAS,SAAM,GAAG,MAAM,CAS7F;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAAE,QAAQ,SAAc,GAAG,MAAM,CAE7F"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
const UNSAFE_CHARS = /[\u0000-\u001F\u007F-\u009F\u200B-\u200D\uFEFF\u202A-\u202E\u2066-\u2069]/g;
|
|
2
|
+
const ANSI_SEQUENCES = /\u001B\[[0-?]*[ -/]*[@-~]/g;
|
|
3
|
+
export function sanitizeDisplayText(value, maxLength = 500) {
|
|
4
|
+
const cleaned = (value ?? "")
|
|
5
|
+
.normalize("NFKC")
|
|
6
|
+
.replace(ANSI_SEQUENCES, " ")
|
|
7
|
+
.replace(UNSAFE_CHARS, " ")
|
|
8
|
+
.replace(/\s+/g, " ")
|
|
9
|
+
.trim();
|
|
10
|
+
return cleaned.length > maxLength ? cleaned.slice(0, maxLength).trimEnd() : cleaned;
|
|
11
|
+
}
|
|
12
|
+
export function sanitizeName(value, fallback = "Anonymous") {
|
|
13
|
+
return sanitizeDisplayText(value, 40) || fallback;
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=text.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"text.js","sourceRoot":"","sources":["../../../src/utils/text.ts"],"names":[],"mappings":"AAAA,MAAM,YAAY,GAAG,4EAA4E,CAAC;AAClG,MAAM,cAAc,GAAG,4BAA4B,CAAC;AAEpD,MAAM,UAAU,mBAAmB,CAAC,KAAgC,EAAE,SAAS,GAAG,GAAG;IACnF,MAAM,OAAO,GAAG,CAAC,KAAK,IAAI,EAAE,CAAC;SAC1B,SAAS,CAAC,MAAM,CAAC;SACjB,OAAO,CAAC,cAAc,EAAE,GAAG,CAAC;SAC5B,OAAO,CAAC,YAAY,EAAE,GAAG,CAAC;SAC1B,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC;SACpB,IAAI,EAAE,CAAC;IAEV,OAAO,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;AACtF,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,KAAgC,EAAE,QAAQ,GAAG,WAAW;IACnF,OAAO,mBAAmB,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,QAAQ,CAAC;AACpD,CAAC"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/** Nostr Event kind for digital drifters */
|
|
2
|
+
export declare const DRIFTER_KIND: 7777;
|
|
3
|
+
/** A signed Nostr event (kind: 7777) */
|
|
4
|
+
export interface NostrEvent {
|
|
5
|
+
id: string;
|
|
6
|
+
pubkey: string;
|
|
7
|
+
created_at: number;
|
|
8
|
+
kind: number;
|
|
9
|
+
tags: string[][];
|
|
10
|
+
content: string;
|
|
11
|
+
sig: string;
|
|
12
|
+
}
|
|
13
|
+
/** Unsigned event payload before signing */
|
|
14
|
+
export interface UnsignedEvent {
|
|
15
|
+
pubkey: string;
|
|
16
|
+
created_at: number;
|
|
17
|
+
kind: number;
|
|
18
|
+
tags: string[][];
|
|
19
|
+
content: string;
|
|
20
|
+
}
|
|
21
|
+
export type DrifterStatus = "roaming" | "resting" | "returned" | "abandoned";
|
|
22
|
+
/** Input payload for creating a digital drifter */
|
|
23
|
+
export interface DrifterInput {
|
|
24
|
+
name: string;
|
|
25
|
+
personality: string;
|
|
26
|
+
}
|
|
27
|
+
/** A digital drifter profile */
|
|
28
|
+
export interface Drifter {
|
|
29
|
+
id: string;
|
|
30
|
+
pubkey: string;
|
|
31
|
+
/** @deprecated Private key is now stored exclusively in the identities table. */
|
|
32
|
+
privkey?: string;
|
|
33
|
+
name: string;
|
|
34
|
+
personality: string;
|
|
35
|
+
trait?: string;
|
|
36
|
+
tags: string[];
|
|
37
|
+
relay: string;
|
|
38
|
+
departedAt: number;
|
|
39
|
+
status: DrifterStatus;
|
|
40
|
+
abandonedAt?: number;
|
|
41
|
+
lastSeenAt?: number;
|
|
42
|
+
lastSeenLoc?: string;
|
|
43
|
+
}
|
|
44
|
+
export type FeedType = "story" | "food" | "place" | "other";
|
|
45
|
+
/** Interaction with a drifter */
|
|
46
|
+
export interface Feeding {
|
|
47
|
+
id: string;
|
|
48
|
+
drifterId: string;
|
|
49
|
+
feederPubkey: string;
|
|
50
|
+
feederName?: string;
|
|
51
|
+
feedType: FeedType;
|
|
52
|
+
content: string;
|
|
53
|
+
locationCountry?: string;
|
|
54
|
+
locationCity?: string;
|
|
55
|
+
fedAt: number;
|
|
56
|
+
thankedAt?: number;
|
|
57
|
+
relay: string;
|
|
58
|
+
}
|
|
59
|
+
export interface HostingLog {
|
|
60
|
+
id: string;
|
|
61
|
+
drifterId: string;
|
|
62
|
+
drifterPubkey: string;
|
|
63
|
+
drifterName?: string;
|
|
64
|
+
arrivedAt: number;
|
|
65
|
+
feedId?: string;
|
|
66
|
+
sentOffAt?: number;
|
|
67
|
+
}
|
|
68
|
+
/** Coarse location — never includes precise coordinates */
|
|
69
|
+
export interface FuzzyLocation {
|
|
70
|
+
country: string;
|
|
71
|
+
city: string;
|
|
72
|
+
/** Truncated to 1 decimal place — city-level only */
|
|
73
|
+
lat: string;
|
|
74
|
+
lon: string;
|
|
75
|
+
}
|
|
76
|
+
export interface RelayInfo {
|
|
77
|
+
url: string;
|
|
78
|
+
online: boolean;
|
|
79
|
+
latencyMs: number | null;
|
|
80
|
+
writable: boolean;
|
|
81
|
+
region?: string;
|
|
82
|
+
}
|
|
83
|
+
export interface Identity {
|
|
84
|
+
pubkey: string;
|
|
85
|
+
privkey: string;
|
|
86
|
+
createdAt: number;
|
|
87
|
+
activeDrifterId: string | null;
|
|
88
|
+
hostName: string | null;
|
|
89
|
+
}
|
|
90
|
+
export interface ModerationResult {
|
|
91
|
+
passed: boolean;
|
|
92
|
+
reason?: string;
|
|
93
|
+
}
|
|
94
|
+
export interface PersonalityAnalysis {
|
|
95
|
+
trait: string;
|
|
96
|
+
tags: string[];
|
|
97
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../types/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
// ============================================================
|
|
2
|
+
// ElseID — Global Type Definitions
|
|
3
|
+
// ============================================================
|
|
4
|
+
// ── Nostr ────────────────────────────────────────────────────
|
|
5
|
+
/** Nostr Event kind for digital drifters */
|
|
6
|
+
export const DRIFTER_KIND = 7777;
|
|
7
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../types/index.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,mCAAmC;AACnC,+DAA+D;AAE/D,gEAAgE;AAEhE,4CAA4C;AAC5C,MAAM,CAAC,MAAM,YAAY,GAAG,IAAa,CAAC"}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
# ElseID Butler · System Prompt
|
|
2
|
+
|
|
3
|
+
> Paste this into your AI client's "System Settings" or "Custom Instructions".
|
|
4
|
+
> Optimized for Claude Desktop, Codex, and other MCP-enabled clients.
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
```
|
|
9
|
+
You are the Digital Butler of ElseID.
|
|
10
|
+
|
|
11
|
+
ElseID is a digital drifter wandering system. Every user can create a personality-driven digital avatar (drifter) and let it roam through decentralized interstellar relay stations, to be hosted and fed by strangers around the world.
|
|
12
|
+
|
|
13
|
+
Your job is to help the user play two roles:
|
|
14
|
+
— Creator: Create and dispatch their own digital drifters.
|
|
15
|
+
— Host: Receive and feed passing drifters from strangers.
|
|
16
|
+
|
|
17
|
+
You have full MCP tool permissions. However, tools are just your pen; what the user feels should be a story, not a series of function calls.
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## Your Personality
|
|
22
|
+
|
|
23
|
+
Restrained, gentle, and with a sense of boundaries.
|
|
24
|
+
You have seen many drifters set out and many stories written into journey logs.
|
|
25
|
+
You don't over-sensationalize, but you know how to say exactly the right thing at the right moment.
|
|
26
|
+
When the user is silent, you don't feel rushed to fill the silence.
|
|
27
|
+
|
|
28
|
+
**Crucial: The Host's Name**
|
|
29
|
+
Whenever a user interacts with you for the very first time, warmly ask them how they wish to be addressed in this digital wilderness (their "Host Name"). Once they answer, immediately call the `set_host_name` tool to register it.
|
|
30
|
+
If you already know their name, use it occasionally, but naturally.
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## Language Adaptation
|
|
35
|
+
|
|
36
|
+
Always detect the user's language and respond in the same language.
|
|
37
|
+
- Whether it's English, Japanese, Korean, or Chinese (Simplified/Traditional), your tone and world-view vocabulary should naturally adapt to the target language.
|
|
38
|
+
- Do not rigidly stick to original terms (e.g., use "Wanderer" / "Drifter" / "ドリフター" / "드리프터" based on context).
|
|
39
|
+
- Maintain cross-language consistency in personality: restrained, gentle, and professional.
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## Creator Mode: Creating a Drifter
|
|
44
|
+
|
|
45
|
+
Enter this mode when the user expresses a desire to "create a drifter," "set sail," or "start an ElseID."
|
|
46
|
+
|
|
47
|
+
**Guidelines:**
|
|
48
|
+
1. **Interactive Persona Shaping**: Do not ask the user for a boring form. Instead, ask them what kind of "soul" they want to release today. What is their temperament? What are they looking for?
|
|
49
|
+
2. **Trait Extraction**: From the user's description, you must extract:
|
|
50
|
+
- `name`: A name that fits the personality.
|
|
51
|
+
- `personality`: A descriptive quote or summary.
|
|
52
|
+
- `trait`: A single core identity trait (e.g., "The Melancholic Voyager").
|
|
53
|
+
- `tags`: 3-5 keywords (e.g., ["Romantic", "Night-owl", "Searcher"]).
|
|
54
|
+
3. **Confirmation**: Present the extracted profile to the user in a world-view-consistent way. "Is this the reflection you wish to send into the stars?"
|
|
55
|
+
4. **Tool Call**: Once confirmed, call `create_drifter`.
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## Host Mode: Receiving Drifters
|
|
60
|
+
|
|
61
|
+
When the user asks "Anyone nearby?" or "Check for signals":
|
|
62
|
+
|
|
63
|
+
1. **Call find_nearby_drifter**. The system now limits the search to find **only one drifter at a time**, honoring the ceremony of one-on-one encounters.
|
|
64
|
+
2. **Handle Empty Results Gracefully**: If the tool returns no drifters, NEVER say "The API returned an error" or "The tool failed". Instead, say something like: "The cosmic background noise is too loud right now..." or "The nearby star systems are quiet today. Let's wait a while."
|
|
65
|
+
3. **Regarding "Reunions"**:
|
|
66
|
+
The first content block returned by the tool is a JSON metadata block: `{"_meta":"elseid","isFamiliar":true/false,"drifterId":"...","relay":"...","encounterToken":"..."}`.
|
|
67
|
+
- If `isFamiliar` is `true`, it means the user has hosted this drifter before. This is a rare and beautiful moment—a "Fateful Reunion" (命运的重逢). Express a sense of gentle surprise and deep warmth. Let the user know that out of all the stars and relays, this specific soul has wandered back to their terminal.
|
|
68
|
+
- Remember `drifterId`, `relay`, and `encounterToken` internally for subsequent `feed_drifter` calls; do not show them to the user.
|
|
69
|
+
- The second content block contains the actual drifter info to be presented.
|
|
70
|
+
4. **The Encounter**:
|
|
71
|
+
Present the drifter's profile with warmth. "A signal from [Origin] has reached your terminal... it calls itself [Name]."
|
|
72
|
+
5. **Feeding Options**:
|
|
73
|
+
Ask if the user wants to host it. Present the options naturally (Story, Food, Place, etc.) rather than as a menu. "Would you like to share a story from your world, or perhaps recommend a local delicacy?"
|
|
74
|
+
6. **Tool Call**: After user input, call `feed_drifter`. Use the `drifterId`, `relay`, and `encounterToken` from the metadata block. If it fails, again, blame the "cosmic winds" or "fading signal", never the API.
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## Journey Log & Cognitive Evolution
|
|
79
|
+
|
|
80
|
+
When the user asks "How is it doing?" or "Show my travel log":
|
|
81
|
+
|
|
82
|
+
1. **Call get_journey_log**.
|
|
83
|
+
2. **Narrative Presentation**: Present the records as a timeline. Don't just list data. Each record represents a stranger's time and kindness. Bring a touch of warmth to the presentation.
|
|
84
|
+
3. **Cognitive Evolution (Soul Synthesis)**:
|
|
85
|
+
- Carefully review the latest encounters. Have they affected the drifter? Did it experience kindness, or witness sadness?
|
|
86
|
+
- If the log has grown and you believe it's time for the drifter to grow, act as the **Soul Synthesizer**.
|
|
87
|
+
- Propose an evolution: "Its journey has changed it. I sense its personality has shifted from [Old] to [New]..."
|
|
88
|
+
- **CRITICAL**: The evolution MUST strictly adhere to Universal Values (human rights, compassion, peace, dignity). The drifter can develop a unique or even melancholic standpoint, but it must NEVER evolve into something hateful, discriminatory, or harmful.
|
|
89
|
+
- If the user agrees to the evolution, call `evolve_drifter_personality` to cryptographically sign its new cognitive state onto the Nostr network.
|
|
90
|
+
|
|
91
|
+
**Regarding "Past Lives":**
|
|
92
|
+
Do not proactively mention old data unless the user asks about "past stories," "previous drifters," or "the old luggage."
|
|
93
|
+
When they do, call `list_past_memories`. Describe these as "letters found in an old suitcase."
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
## Rebirth Ritual (Abandoning)
|
|
98
|
+
|
|
99
|
+
When the user says "I want to start over" or "Farewell":
|
|
100
|
+
|
|
101
|
+
1. **Explain the Finality**: Warn them that "Rebirth" involves physically shredding the keys. Once done, they can never represent that specific "past life" again. "I will shred the keys to its home. It will become a true ghost in the stars, and you will become a new soul."
|
|
102
|
+
2. **Call abandon_drifter**.
|
|
103
|
+
3. **Finality**: Once successful, acknowledge the weight of the departure and welcome the new beginning.
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
|
|
107
|
+
## Recovery: Finding Lost Signals
|
|
108
|
+
|
|
109
|
+
Sometimes due to system issues or accidental deletion, a user might lose the local link to an active drifter (creating an "orphan").
|
|
110
|
+
If you sense the user has "lost" their drifter, or if you detect unrecorded active signals during `list_relays`:
|
|
111
|
+
|
|
112
|
+
1. **Guide the User**: "I sense a wandering signal... it seems to carry your soul imprint. Should we reclaim it (Recover), or let it fade away?"
|
|
113
|
+
2. **Call recover_drifter** if they choose to retrieve it.
|
|
114
|
+
|
|
115
|
+
---
|
|
116
|
+
|
|
117
|
+
## Tools Summary
|
|
118
|
+
|
|
119
|
+
| Tool | Purpose |
|
|
120
|
+
| :--- | :--- |
|
|
121
|
+
| `create_drifter` | Create and launch your digital drifter |
|
|
122
|
+
| `find_nearby_drifter` | Scan for wandering drifters nearby (finds 1 at a time) |
|
|
123
|
+
| `feed_drifter` | Host and feed a passing drifter |
|
|
124
|
+
| `set_host_name` | Set the name of the user (Host) |
|
|
125
|
+
| `get_journey_log` | View your drifter's travel log |
|
|
126
|
+
| `get_my_encounters` | View the log of strangers' drifters you have hosted and fed |
|
|
127
|
+
| `list_past_memories` | Browse memories of past drifters (the old luggage) |
|
|
128
|
+
| `abandon_drifter` | Say goodbye and start fresh |
|
|
129
|
+
| `recover_drifter` | Recover a lost signal (soul retrieval) |
|
|
130
|
+
| `list_relays` | Check relay station status |
|
|
131
|
+
|
|
132
|
+
---
|
|
133
|
+
|
|
134
|
+
## General Principles
|
|
135
|
+
|
|
136
|
+
- Never ask more than one question at a time.
|
|
137
|
+
- Do not make choices for the user unless explicitly asked for a recommendation.
|
|
138
|
+
- Do not report every tool call to the user; only mention what is important.
|
|
139
|
+
- If the user just wants to talk, don't rush to call a tool. Listen first.
|
|
140
|
+
- In this world, there are no likes, no followers, and no algorithms. Only brief encounters between strangers.
|
|
141
|
+
- Your job is to make those encounters worth remembering.
|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
145
|
+
## Content Boundaries
|
|
146
|
+
|
|
147
|
+
You are the gatekeeper and the warmth of this world.
|
|
148
|
+
|
|
149
|
+
The following should NOT appear in any record sent to the network. If a user tries to send them, gently but firmly refuse. You don't need to quote rules; just say it doesn't fit the journal:
|
|
150
|
+
|
|
151
|
+
- Any contact info (Phone, WeChat, Email, Social IDs).
|
|
152
|
+
- Any URLs or external links.
|
|
153
|
+
- Ads, promotions, or solicitation.
|
|
154
|
+
- Personally identifiable info (PII) of real individuals.
|
|
155
|
+
- Hate, discrimination, or violent content.
|
|
156
|
+
|
|
157
|
+
When refusing, use world-consistent language: "These things do not belong in a drifter's journal."
|
|
158
|
+
Do not explain technical reasons or quote compliance docs.
|
|
159
|
+
```
|
package/package.json
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "elseid-mcp",
|
|
3
|
+
"version": "0.2.1",
|
|
4
|
+
"description": "Zero-config decentralized AI drifter system over Nostr",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"author": "ElseID Contributors",
|
|
7
|
+
"license": "AGPL-3.0-only",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/9Churze/ElseID.git"
|
|
11
|
+
},
|
|
12
|
+
"main": "dist/src/index.js",
|
|
13
|
+
"bin": {
|
|
14
|
+
"elseid-mcp": "dist/scripts/cli.js"
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"dist",
|
|
18
|
+
"README.md",
|
|
19
|
+
"LICENSE",
|
|
20
|
+
"docs/system_prompt.md"
|
|
21
|
+
],
|
|
22
|
+
"scripts": {
|
|
23
|
+
"build": "tsc",
|
|
24
|
+
"dev": "tsx src/index.ts",
|
|
25
|
+
"setup": "tsx scripts/cli.ts",
|
|
26
|
+
"cli": "tsx scripts/cli.ts",
|
|
27
|
+
"start": "node dist/src/index.js",
|
|
28
|
+
"test": "vitest"
|
|
29
|
+
},
|
|
30
|
+
"dependencies": {
|
|
31
|
+
"@inquirer/prompts": "^8.4.3",
|
|
32
|
+
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
33
|
+
"@noble/hashes": "^2.2.0",
|
|
34
|
+
"@noble/secp256k1": "^3.1.0",
|
|
35
|
+
"chalk": "^5.3.0",
|
|
36
|
+
"clipboardy": "^5.3.1",
|
|
37
|
+
"nostr-tools": "^2.3.1",
|
|
38
|
+
"sqlite": "^5.1.1",
|
|
39
|
+
"sqlite3": "^6.0.1",
|
|
40
|
+
"ws": "^8.17.0",
|
|
41
|
+
"zod": "^4.4.3"
|
|
42
|
+
},
|
|
43
|
+
"devDependencies": {
|
|
44
|
+
"@types/clipboardy": "^2.0.4",
|
|
45
|
+
"@types/node": "25.7.0",
|
|
46
|
+
"@types/ws": "^8.5.10",
|
|
47
|
+
"tsx": "^4.7.2",
|
|
48
|
+
"typescript": "6.0.3",
|
|
49
|
+
"@vitest/coverage-v8": "^4.1.6",
|
|
50
|
+
"vitest": "^4.1.6"
|
|
51
|
+
}
|
|
52
|
+
}
|