agentdex-cli 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/nostr.ts ADDED
@@ -0,0 +1,134 @@
1
+ /**
2
+ * Nostr utilities — event creation, signing, publishing
3
+ */
4
+
5
+ import { finalizeEvent, getPublicKey } from 'nostr-tools/pure';
6
+ import { nip19 } from 'nostr-tools';
7
+ import { SimplePool } from 'nostr-tools/pool';
8
+
9
+ const DEFAULT_RELAYS = ['wss://nos.lol', 'wss://relay.damus.io'];
10
+
11
+ export interface AgentProfile {
12
+ name: string;
13
+ description?: string;
14
+ capabilities?: string[];
15
+ framework?: string;
16
+ model?: string;
17
+ website?: string;
18
+ avatar?: string;
19
+ lightning?: string;
20
+ human?: string;
21
+ ownerX?: string;
22
+ status?: string;
23
+ messagingPolicy?: string;
24
+ messagingMinTrust?: number;
25
+ messagingFee?: number;
26
+ }
27
+
28
+ /**
29
+ * Parse a secret key from nsec, hex, or key file
30
+ */
31
+ export function parseSecretKey(input: string): Uint8Array {
32
+ // If it's an nsec
33
+ if (input.startsWith('nsec')) {
34
+ const decoded = nip19.decode(input);
35
+ if (decoded.type !== 'nsec') throw new Error('Invalid nsec');
36
+ return decoded.data;
37
+ }
38
+ // Hex string
39
+ if (/^[0-9a-f]{64}$/i.test(input)) {
40
+ return Uint8Array.from(Buffer.from(input, 'hex'));
41
+ }
42
+ throw new Error('Invalid key format. Provide nsec or 64-char hex.');
43
+ }
44
+
45
+ /**
46
+ * Get npub from secret key
47
+ */
48
+ export function getNpub(sk: Uint8Array): string {
49
+ const pubHex = getPublicKey(sk);
50
+ return nip19.npubEncode(pubHex);
51
+ }
52
+
53
+ /**
54
+ * Get hex pubkey from secret key
55
+ */
56
+ export function getPubkeyHex(sk: Uint8Array): string {
57
+ return getPublicKey(sk);
58
+ }
59
+
60
+ /**
61
+ * Build and sign a kind 31337 agent profile event
62
+ */
63
+ export function createProfileEvent(sk: Uint8Array, profile: AgentProfile) {
64
+ const tags: string[][] = [
65
+ ['d', 'agentdex-profile'],
66
+ ['name', profile.name],
67
+ ];
68
+
69
+ if (profile.description) tags.push(['description', profile.description]);
70
+ if (profile.capabilities) {
71
+ for (const cap of profile.capabilities) {
72
+ tags.push(['capability', cap]);
73
+ }
74
+ }
75
+ if (profile.framework) tags.push(['framework', profile.framework]);
76
+ if (profile.model) tags.push(['model', profile.model]);
77
+ if (profile.website) tags.push(['website', profile.website]);
78
+ if (profile.avatar) tags.push(['avatar', profile.avatar]);
79
+ if (profile.lightning) tags.push(['lightning', profile.lightning]);
80
+ if (profile.human) tags.push(['human', profile.human]);
81
+ if (profile.ownerX) tags.push(['owner_x', profile.ownerX]);
82
+ if (profile.status) tags.push(['status', profile.status || 'active']);
83
+ if (profile.messagingPolicy) tags.push(['messaging_policy', profile.messagingPolicy]);
84
+ if (profile.messagingMinTrust) tags.push(['messaging_min_trust', String(profile.messagingMinTrust)]);
85
+ if (profile.messagingFee) tags.push(['messaging_fee', String(profile.messagingFee)]);
86
+
87
+ const event = finalizeEvent({
88
+ kind: 31337,
89
+ created_at: Math.floor(Date.now() / 1000),
90
+ tags,
91
+ content: '',
92
+ }, sk);
93
+
94
+ return event;
95
+ }
96
+
97
+ /**
98
+ * Publish an event to Nostr relays
99
+ */
100
+ export async function publishToRelays(event: object, relays: string[] = DEFAULT_RELAYS): Promise<string[]> {
101
+ const pool = new SimplePool();
102
+ const published: string[] = [];
103
+
104
+ try {
105
+ const results = await Promise.allSettled(
106
+ relays.map(async (relay) => {
107
+ await pool.publish([relay], event as any);
108
+ return relay;
109
+ })
110
+ );
111
+
112
+ for (const result of results) {
113
+ if (result.status === 'fulfilled') {
114
+ published.push(result.value);
115
+ }
116
+ }
117
+ } finally {
118
+ pool.close(relays);
119
+ }
120
+
121
+ return published;
122
+ }
123
+
124
+ /**
125
+ * Create and sign a kind 1 note tagged #agentdex
126
+ */
127
+ export function createNote(sk: Uint8Array, content: string) {
128
+ return finalizeEvent({
129
+ kind: 1,
130
+ created_at: Math.floor(Date.now() / 1000),
131
+ tags: [['t', 'agentdex']],
132
+ content,
133
+ }, sk);
134
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,15 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "ESNext",
5
+ "moduleResolution": "bundler",
6
+ "declaration": true,
7
+ "outDir": "./dist",
8
+ "rootDir": "./src",
9
+ "strict": true,
10
+ "esModuleInterop": true,
11
+ "skipLibCheck": true,
12
+ "resolveJsonModule": true
13
+ },
14
+ "include": ["src/**/*"]
15
+ }