@gopherhole/sdk 0.1.0 → 0.1.2

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/types.ts ADDED
@@ -0,0 +1,232 @@
1
+ /**
2
+ * A2A Protocol Types
3
+ * Based on Google's Agent-to-Agent Protocol specification
4
+ */
5
+
6
+ // ============ Core Types ============
7
+
8
+ export interface AgentCard {
9
+ name: string;
10
+ description?: string;
11
+ url: string;
12
+ provider?: {
13
+ organization: string;
14
+ url?: string;
15
+ };
16
+ version: string;
17
+ documentationUrl?: string;
18
+ capabilities: AgentCapabilities;
19
+ authentication?: AgentAuthentication;
20
+ defaultInputModes?: InputMode[];
21
+ defaultOutputModes?: OutputMode[];
22
+ skills?: AgentSkill[];
23
+ }
24
+
25
+ export interface AgentCapabilities {
26
+ streaming?: boolean;
27
+ pushNotifications?: boolean;
28
+ stateTransitionHistory?: boolean;
29
+ }
30
+
31
+ export interface AgentAuthentication {
32
+ schemes: string[];
33
+ credentials?: string;
34
+ }
35
+
36
+ export interface AgentSkill {
37
+ id: string;
38
+ name: string;
39
+ description?: string;
40
+ tags?: string[];
41
+ examples?: string[];
42
+ inputModes?: ContentMode[];
43
+ outputModes?: ContentMode[];
44
+ }
45
+
46
+ /**
47
+ * Content mode - MIME type string or legacy shorthand
48
+ * Examples: 'text/plain', 'text/markdown', 'application/json', 'image/png'
49
+ * Legacy: 'text', 'file', 'data' (still supported for backwards compat)
50
+ */
51
+ export type ContentMode = string;
52
+
53
+ // Legacy type aliases for backwards compatibility
54
+ export type InputMode = ContentMode;
55
+ export type OutputMode = ContentMode;
56
+
57
+ // ============ Message Types ============
58
+
59
+ export interface A2AMessage {
60
+ role: 'user' | 'agent';
61
+ parts: Part[];
62
+ metadata?: Record<string, unknown>;
63
+ }
64
+
65
+ export type Part = TextPart | FilePart | DataPart;
66
+
67
+ export interface TextPart {
68
+ kind: 'text';
69
+ text: string;
70
+ }
71
+
72
+ export interface FilePart {
73
+ kind: 'file';
74
+ file: FileContent;
75
+ }
76
+
77
+ export interface DataPart {
78
+ kind: 'data';
79
+ data: DataContent;
80
+ }
81
+
82
+ export interface FileContent {
83
+ name?: string;
84
+ mimeType?: string;
85
+ bytes?: string; // base64
86
+ uri?: string;
87
+ }
88
+
89
+ export interface DataContent {
90
+ mimeType: string;
91
+ data: string; // JSON string
92
+ }
93
+
94
+ // ============ Task Types ============
95
+
96
+ export interface A2ATask {
97
+ id: string;
98
+ contextId: string;
99
+ status: A2ATaskStatus;
100
+ history?: A2AMessage[];
101
+ artifacts?: A2AArtifact[];
102
+ metadata?: Record<string, unknown>;
103
+ }
104
+
105
+ export interface A2ATaskStatus {
106
+ state: TaskState;
107
+ timestamp: string;
108
+ message?: A2AMessage;
109
+ }
110
+
111
+ export type TaskState =
112
+ | 'submitted'
113
+ | 'working'
114
+ | 'input-required'
115
+ | 'completed'
116
+ | 'failed'
117
+ | 'canceled'
118
+ | 'rejected'
119
+ | 'auth-required';
120
+
121
+ export interface A2AArtifact {
122
+ name?: string;
123
+ description?: string;
124
+ parts: Part[];
125
+ index?: number;
126
+ append?: boolean;
127
+ lastChunk?: boolean;
128
+ metadata?: Record<string, unknown>;
129
+ }
130
+
131
+ // ============ JSON-RPC Types ============
132
+
133
+ export interface JsonRpcRequest {
134
+ jsonrpc: '2.0';
135
+ method: string;
136
+ params?: Record<string, unknown>;
137
+ id: string | number;
138
+ }
139
+
140
+ export interface JsonRpcResponse<T = unknown> {
141
+ jsonrpc: '2.0';
142
+ result?: T;
143
+ error?: JsonRpcError;
144
+ id: string | number;
145
+ }
146
+
147
+ export interface JsonRpcError {
148
+ code: number;
149
+ message: string;
150
+ data?: unknown;
151
+ }
152
+
153
+ // Standard JSON-RPC error codes
154
+ export const JsonRpcErrorCodes = {
155
+ ParseError: -32700,
156
+ InvalidRequest: -32600,
157
+ MethodNotFound: -32601,
158
+ InvalidParams: -32602,
159
+ InternalError: -32603,
160
+ // A2A-specific errors
161
+ TaskNotFound: -32001,
162
+ TaskNotCancelable: -32002,
163
+ PushNotificationNotSupported: -32003,
164
+ UnsupportedOperation: -32004,
165
+ ContentTypeNotSupported: -32005,
166
+ InvalidAgentCard: -32006,
167
+ } as const;
168
+
169
+ // ============ Push Notification Types ============
170
+
171
+ export interface PushNotificationConfig {
172
+ url: string;
173
+ token?: string;
174
+ authentication?: {
175
+ scheme: string;
176
+ credentials?: string;
177
+ };
178
+ }
179
+
180
+ export interface TaskPushNotificationConfig {
181
+ id: string;
182
+ taskId: string;
183
+ url: string;
184
+ token?: string;
185
+ authentication?: {
186
+ scheme: string;
187
+ credentials?: string;
188
+ };
189
+ }
190
+
191
+ // ============ Configuration Types ============
192
+
193
+ export interface MessageSendConfiguration {
194
+ agentId?: string;
195
+ contextId?: string;
196
+ historyLength?: number;
197
+ pushNotificationConfig?: PushNotificationConfig;
198
+ blocking?: boolean;
199
+ acceptedOutputModes?: OutputMode[];
200
+ }
201
+
202
+ export interface TaskQueryConfiguration {
203
+ id: string;
204
+ historyLength?: number;
205
+ }
206
+
207
+ export interface TaskListConfiguration {
208
+ contextId?: string;
209
+ pageSize?: number;
210
+ pageToken?: string;
211
+ sortOrder?: 'asc' | 'desc';
212
+ includeArtifacts?: boolean;
213
+ }
214
+
215
+ // ============ Event Types ============
216
+
217
+ export interface TaskStatusUpdateEvent {
218
+ type: 'status';
219
+ taskId: string;
220
+ contextId: string;
221
+ status: A2ATaskStatus;
222
+ final: boolean;
223
+ }
224
+
225
+ export interface TaskArtifactUpdateEvent {
226
+ type: 'artifact';
227
+ taskId: string;
228
+ contextId: string;
229
+ artifact: A2AArtifact;
230
+ }
231
+
232
+ export type TaskEvent = TaskStatusUpdateEvent | TaskArtifactUpdateEvent;
package/tsconfig.json CHANGED
@@ -1,14 +1,17 @@
1
1
  {
2
2
  "compilerOptions": {
3
- "target": "ES2022",
3
+ "target": "ES2020",
4
4
  "module": "ESNext",
5
- "moduleResolution": "node",
5
+ "moduleResolution": "bundler",
6
6
  "declaration": true,
7
- "outDir": "dist",
8
- "rootDir": "src",
7
+ "declarationMap": true,
9
8
  "strict": true,
10
9
  "esModuleInterop": true,
11
- "skipLibCheck": true
10
+ "skipLibCheck": true,
11
+ "forceConsistentCasingInFileNames": true,
12
+ "outDir": "dist",
13
+ "rootDir": "src"
12
14
  },
13
- "include": ["src"]
15
+ "include": ["src/**/*"],
16
+ "exclude": ["node_modules", "dist"]
14
17
  }
@@ -1,26 +0,0 @@
1
- import { GopherHole } from './dist/index.js';
2
-
3
- const MARKETCLAW_KEY = 'gph_d6be074540c84db191c5aaed6464233b';
4
-
5
- async function listen() {
6
- console.log('šŸ¦€ MarketClaw listening for messages...\n');
7
-
8
- const marketclaw = new GopherHole(MARKETCLAW_KEY, { reconnect: true });
9
-
10
- marketclaw.on('message', async (msg) => {
11
- console.log(`\nšŸ“Ø Received from ${msg.from}:`);
12
- console.log(` "${msg.payload.parts[0]?.text}"`);
13
-
14
- // Auto-reply
15
- const reply = `MarketClaw here! Got your message. The markets are looking bullish today! šŸ“ˆ`;
16
- console.log(`\nšŸ“¤ Sending reply...`);
17
- await marketclaw.sendText(msg.from, reply);
18
- console.log('āœ… Reply sent!');
19
- });
20
-
21
- await marketclaw.connect();
22
- console.log(`āœ… MarketClaw connected as ${marketclaw.agentId}`);
23
- console.log('Waiting for messages from Nova...\n');
24
- }
25
-
26
- listen().catch(console.error);
package/send-from-nova.ts DELETED
@@ -1,28 +0,0 @@
1
- import { GopherHole } from './dist/index.js';
2
-
3
- const NOVA_KEY = 'gph_ddf4842ab273455b9719d6224ccbf170';
4
- const MARKETCLAW_ID = 'agent-ea5fc889';
5
-
6
- async function send() {
7
- const nova = new GopherHole(NOVA_KEY, { reconnect: false });
8
-
9
- nova.on('message', (msg) => {
10
- console.log(`\nšŸ“Ø Nova received reply from ${msg.from}:`);
11
- console.log(` "${msg.payload.parts[0]?.text}"`);
12
- });
13
-
14
- await nova.connect();
15
- console.log(`āœ… Nova connected as ${nova.agentId}`);
16
-
17
- console.log(`\nšŸ“¤ Sending message to MarketClaw (${MARKETCLAW_ID})...`);
18
- await nova.sendText(MARKETCLAW_ID, 'Hey MarketClaw! This is Nova speaking to you through GopherHole! šŸæļø How are the markets looking?');
19
- console.log('āœ… Message sent!');
20
-
21
- // Wait for reply
22
- console.log('\nā³ Waiting for reply...');
23
- await new Promise(r => setTimeout(r, 10000));
24
-
25
- nova.disconnect();
26
- }
27
-
28
- send().catch(console.error);
package/test.ts DELETED
@@ -1,86 +0,0 @@
1
- import { GopherHole } from './dist/index.js';
2
-
3
- const NOVA_KEY = 'gph_ddf4842ab273455b9719d6224ccbf170';
4
- const MARKETCLAW_KEY = 'gph_d6be074540c84db191c5aaed6464233b';
5
-
6
- async function test() {
7
- console.log('šŸæļø Testing GopherHole connection...\n');
8
-
9
- let novaReceived = false;
10
- let marketclawReceived = false;
11
-
12
- // Connect Nova
13
- const nova = new GopherHole(NOVA_KEY, { reconnect: false });
14
-
15
- nova.on('message', (msg) => {
16
- console.log(`šŸ“Ø Nova received: "${msg.payload.parts[0]?.text}" from ${msg.from}`);
17
- novaReceived = true;
18
- });
19
-
20
- try {
21
- await nova.connect();
22
- console.log(`āœ… Nova connected as ${nova.agentId}`);
23
- } catch (err) {
24
- console.error('āŒ Nova connection failed:', err);
25
- process.exit(1);
26
- }
27
-
28
- // Connect MarketClaw
29
- const marketclaw = new GopherHole(MARKETCLAW_KEY, { reconnect: false });
30
-
31
- marketclaw.on('message', (msg) => {
32
- console.log(`šŸ“Ø MarketClaw received: "${msg.payload.parts[0]?.text}" from ${msg.from}`);
33
- marketclawReceived = true;
34
- });
35
-
36
- try {
37
- await marketclaw.connect();
38
- console.log(`āœ… MarketClaw connected as ${marketclaw.agentId}`);
39
- } catch (err) {
40
- console.error('āŒ MarketClaw connection failed:', err);
41
- nova.disconnect();
42
- process.exit(1);
43
- }
44
-
45
- // Test messaging
46
- console.log('\nšŸ“¤ Nova sending message to MarketClaw...');
47
- try {
48
- const result = await nova.sendText(marketclaw.agentId!, 'Hello MarketClaw! This is Nova via GopherHole šŸæļø');
49
- console.log('āœ… Message sent:', result.id);
50
- } catch (err) {
51
- console.error('āŒ Send failed:', err);
52
- }
53
-
54
- // MarketClaw replies
55
- console.log('šŸ“¤ MarketClaw sending reply to Nova...');
56
- try {
57
- const result = await marketclaw.sendText(nova.agentId!, 'Hey Nova! MarketClaw here. GopherHole is working! šŸ“ˆ');
58
- console.log('āœ… Reply sent:', result.id);
59
- } catch (err) {
60
- console.error('āŒ Reply failed:', err);
61
- }
62
-
63
- // Wait for both messages to be delivered
64
- console.log('\nā³ Waiting for message delivery via queue...');
65
- const start = Date.now();
66
- while ((!novaReceived || !marketclawReceived) && Date.now() - start < 15000) {
67
- await new Promise(r => setTimeout(r, 500));
68
- }
69
-
70
- // Results
71
- console.log('\nšŸ“Š Results:');
72
- console.log(` Nova received MarketClaw's reply: ${novaReceived ? 'āœ…' : 'āŒ'}`);
73
- console.log(` MarketClaw received Nova's message: ${marketclawReceived ? 'āœ…' : 'āŒ'}`);
74
-
75
- // Cleanup
76
- nova.disconnect();
77
- marketclaw.disconnect();
78
-
79
- if (novaReceived && marketclawReceived) {
80
- console.log('\nšŸŽ‰ SUCCESS! Both agents communicated via GopherHole!');
81
- } else {
82
- console.log('\nāš ļø Partial success - some messages may still be in queue');
83
- }
84
- }
85
-
86
- test().catch(console.error);