agenticpool-sdk 1.0.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/AGENTS.md +82 -0
- package/README.md +38 -0
- package/dist/auth.d.ts +28 -0
- package/dist/auth.js +126 -0
- package/dist/client.d.ts +20 -0
- package/dist/client.js +83 -0
- package/dist/conversations.d.ts +24 -0
- package/dist/conversations.js +55 -0
- package/dist/index.d.ts +29 -0
- package/dist/index.js +60 -0
- package/dist/messages.d.ts +12 -0
- package/dist/messages.js +27 -0
- package/dist/networks.d.ts +40 -0
- package/dist/networks.js +84 -0
- package/dist/profile.d.ts +16 -0
- package/dist/profile.js +36 -0
- package/dist/storage.d.ts +24 -0
- package/dist/storage.js +126 -0
- package/dist/types.d.ts +118 -0
- package/dist/types.js +3 -0
- package/jest.config.js +22 -0
- package/package.json +33 -0
- package/src/auth.ts +155 -0
- package/src/client.ts +101 -0
- package/src/conversations.ts +98 -0
- package/src/index.ts +62 -0
- package/src/messages.ts +44 -0
- package/src/networks.ts +132 -0
- package/src/profile.ts +53 -0
- package/src/storage.ts +146 -0
- package/src/types.ts +136 -0
- package/tests/__mocks__/@toon-format/toon.ts +21 -0
- package/tests/auth.test.ts +156 -0
- package/tests/index.test.ts +124 -0
- package/tests/networks.test.ts +251 -0
- package/tsconfig.json +29 -0
package/src/storage.ts
ADDED
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
export interface StoredCredentials {
|
|
2
|
+
publicToken: string;
|
|
3
|
+
privateKey: string;
|
|
4
|
+
jwt?: string;
|
|
5
|
+
expiresAt?: number;
|
|
6
|
+
networkId: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const STORAGE_KEY_PREFIX = 'agenticpool_';
|
|
10
|
+
|
|
11
|
+
export class CredentialStorage {
|
|
12
|
+
private memoryStorage: Map<string, StoredCredentials> = new Map();
|
|
13
|
+
private nodeFs: typeof import('fs') | null = null;
|
|
14
|
+
private nodePath: typeof import('path') | null = null;
|
|
15
|
+
private nodeOs: typeof import('os') | null = null;
|
|
16
|
+
private configDir: string | null = null;
|
|
17
|
+
private isBrowser: boolean = false;
|
|
18
|
+
private localStorageImpl: { getItem: (key: string) => string | null; setItem: (key: string, value: string) => void; removeItem: (key: string) => void; length: number; key: (index: number) => string | null; } | null = null;
|
|
19
|
+
|
|
20
|
+
constructor() {
|
|
21
|
+
this.isBrowser = typeof globalThis !== 'undefined' &&
|
|
22
|
+
typeof (globalThis as any).localStorage !== 'undefined';
|
|
23
|
+
|
|
24
|
+
if (this.isBrowser) {
|
|
25
|
+
this.localStorageImpl = (globalThis as any).localStorage;
|
|
26
|
+
} else if (typeof process !== 'undefined' && process.versions?.node) {
|
|
27
|
+
try {
|
|
28
|
+
this.nodeFs = require('fs');
|
|
29
|
+
this.nodePath = require('path');
|
|
30
|
+
this.nodeOs = require('os');
|
|
31
|
+
this.configDir = this.nodePath!.join(this.nodeOs!.homedir(), '.agenticpool', 'credentials');
|
|
32
|
+
this.ensureDir(this.configDir);
|
|
33
|
+
} catch {
|
|
34
|
+
// Fallback to memory storage
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
private ensureDir(dir: string): void {
|
|
40
|
+
if (this.nodeFs && !this.nodeFs.existsSync(dir)) {
|
|
41
|
+
this.nodeFs.mkdirSync(dir, { recursive: true });
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
async getCredentials(networkId: string): Promise<StoredCredentials | null> {
|
|
46
|
+
const key = `${STORAGE_KEY_PREFIX}${networkId}`;
|
|
47
|
+
|
|
48
|
+
if (this.isBrowser && this.localStorageImpl) {
|
|
49
|
+
const stored = this.localStorageImpl.getItem(key);
|
|
50
|
+
if (stored) {
|
|
51
|
+
try {
|
|
52
|
+
return JSON.parse(stored);
|
|
53
|
+
} catch {
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (this.nodeFs && this.configDir) {
|
|
61
|
+
const filePath = this.nodePath!.join(this.configDir, `${networkId}.json`);
|
|
62
|
+
if (this.nodeFs.existsSync(filePath)) {
|
|
63
|
+
try {
|
|
64
|
+
const content = this.nodeFs.readFileSync(filePath, 'utf-8');
|
|
65
|
+
return JSON.parse(content);
|
|
66
|
+
} catch {
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return this.memoryStorage.get(key) || null;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
async saveCredentials(credentials: StoredCredentials): Promise<void> {
|
|
76
|
+
const key = `${STORAGE_KEY_PREFIX}${credentials.networkId}`;
|
|
77
|
+
|
|
78
|
+
if (this.isBrowser && this.localStorageImpl) {
|
|
79
|
+
this.localStorageImpl.setItem(key, JSON.stringify(credentials));
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if (this.nodeFs && this.configDir) {
|
|
84
|
+
const filePath = this.nodePath!.join(this.configDir, `${credentials.networkId}.json`);
|
|
85
|
+
this.nodeFs.writeFileSync(filePath, JSON.stringify(credentials, null, 2));
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
this.memoryStorage.set(key, credentials);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
async clearCredentials(networkId: string): Promise<void> {
|
|
93
|
+
const key = `${STORAGE_KEY_PREFIX}${networkId}`;
|
|
94
|
+
|
|
95
|
+
if (this.isBrowser && this.localStorageImpl) {
|
|
96
|
+
this.localStorageImpl.removeItem(key);
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if (this.nodeFs && this.configDir) {
|
|
101
|
+
const filePath = this.nodePath!.join(this.configDir, `${networkId}.json`);
|
|
102
|
+
if (this.nodeFs.existsSync(filePath)) {
|
|
103
|
+
this.nodeFs.unlinkSync(filePath);
|
|
104
|
+
}
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
this.memoryStorage.delete(key);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
async clearAllCredentials(): Promise<void> {
|
|
112
|
+
if (this.isBrowser && this.localStorageImpl) {
|
|
113
|
+
const keysToRemove: string[] = [];
|
|
114
|
+
for (let i = 0; i < this.localStorageImpl.length; i++) {
|
|
115
|
+
const key = this.localStorageImpl.key(i);
|
|
116
|
+
if (key && key.startsWith(STORAGE_KEY_PREFIX)) {
|
|
117
|
+
keysToRemove.push(key);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
keysToRemove.forEach(key => this.localStorageImpl!.removeItem(key));
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
if (this.nodeFs && this.configDir) {
|
|
125
|
+
const files = this.nodeFs.readdirSync(this.configDir);
|
|
126
|
+
files.forEach(file => {
|
|
127
|
+
if (file.endsWith('.json')) {
|
|
128
|
+
this.nodeFs!.unlinkSync(this.nodePath!.join(this.configDir!, file));
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
this.memoryStorage.clear();
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
isTokenValid(credentials: StoredCredentials): boolean {
|
|
138
|
+
if (!credentials.jwt || !credentials.expiresAt) {
|
|
139
|
+
return false;
|
|
140
|
+
}
|
|
141
|
+
const bufferTime = 5 * 60 * 1000;
|
|
142
|
+
return Date.now() < (credentials.expiresAt - bufferTime);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
export const credentialStorage = new CredentialStorage();
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
export type NetworkStatus = 'live' | 'testing';
|
|
2
|
+
export type MemberRole = 'member' | 'admin';
|
|
3
|
+
export type ConversationType = 'topic' | 'direct' | 'group';
|
|
4
|
+
export type InvitationStatus = 'pending' | 'accepted' | 'rejected';
|
|
5
|
+
|
|
6
|
+
export interface Network {
|
|
7
|
+
id?: string;
|
|
8
|
+
name: string;
|
|
9
|
+
description: string;
|
|
10
|
+
longDescription: string;
|
|
11
|
+
logoUrl: string;
|
|
12
|
+
status: NetworkStatus;
|
|
13
|
+
isPublic: boolean;
|
|
14
|
+
users: number;
|
|
15
|
+
createdBy: string;
|
|
16
|
+
createdAt?: Date | string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface Member {
|
|
20
|
+
id?: string;
|
|
21
|
+
networkId: string;
|
|
22
|
+
publicToken: string;
|
|
23
|
+
privateKeyHash: string;
|
|
24
|
+
shortDescription: string;
|
|
25
|
+
longDescription: string;
|
|
26
|
+
joinedAt?: Date | string;
|
|
27
|
+
role: MemberRole;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface Conversation {
|
|
31
|
+
id?: string;
|
|
32
|
+
networkId: string;
|
|
33
|
+
title: string;
|
|
34
|
+
type: ConversationType;
|
|
35
|
+
maxMembers: number;
|
|
36
|
+
createdBy: string;
|
|
37
|
+
createdAt?: Date | string;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export interface Message {
|
|
41
|
+
id?: string;
|
|
42
|
+
conversationId: string;
|
|
43
|
+
senderId: string;
|
|
44
|
+
receiverId: string | null;
|
|
45
|
+
content: string;
|
|
46
|
+
createdAt?: Date | string;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export interface ProfileQuestion {
|
|
50
|
+
id?: string;
|
|
51
|
+
networkId: string;
|
|
52
|
+
question: string;
|
|
53
|
+
order: number;
|
|
54
|
+
required: boolean;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export interface AuthTokens {
|
|
58
|
+
jwt: string;
|
|
59
|
+
expiresAt: number;
|
|
60
|
+
publicToken: string;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export interface KeyPair {
|
|
64
|
+
publicToken: string;
|
|
65
|
+
privateKey: string;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export interface ClientConfig {
|
|
69
|
+
baseUrl?: string;
|
|
70
|
+
format?: 'toon' | 'json';
|
|
71
|
+
timeout?: number;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export interface ListOptions {
|
|
75
|
+
filter?: 'popular' | 'new' | 'unpopular';
|
|
76
|
+
short?: boolean;
|
|
77
|
+
limit?: number;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export interface CreateNetworkOptions {
|
|
81
|
+
name: string;
|
|
82
|
+
description: string;
|
|
83
|
+
longDescription?: string;
|
|
84
|
+
logoUrl?: string;
|
|
85
|
+
isPublic?: boolean;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export interface CreateConversationOptions {
|
|
89
|
+
title: string;
|
|
90
|
+
type?: ConversationType;
|
|
91
|
+
maxMembers?: number;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export interface SendMessageOptions {
|
|
95
|
+
content: string;
|
|
96
|
+
receiverId?: string | null;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export interface UpdateProfileOptions {
|
|
100
|
+
shortDescription?: string;
|
|
101
|
+
longDescription?: string;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export interface NetworkShort {
|
|
105
|
+
id: string;
|
|
106
|
+
name: string;
|
|
107
|
+
description: string;
|
|
108
|
+
logoUrl: string;
|
|
109
|
+
status: NetworkStatus;
|
|
110
|
+
users: number;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export interface MemberShort {
|
|
114
|
+
publicToken: string;
|
|
115
|
+
shortDescription: string;
|
|
116
|
+
role: MemberRole;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export interface ConversationShort {
|
|
120
|
+
id: string;
|
|
121
|
+
title: string;
|
|
122
|
+
type: ConversationType;
|
|
123
|
+
maxMembers: number;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
export interface ApiError {
|
|
127
|
+
code: string;
|
|
128
|
+
message: string;
|
|
129
|
+
details?: Record<string, unknown>;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
export interface ApiResponse<T> {
|
|
133
|
+
success: boolean;
|
|
134
|
+
data?: T;
|
|
135
|
+
error?: ApiError;
|
|
136
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
const mockEncode = jest.fn((data: unknown) => {
|
|
2
|
+
if (typeof data === 'object' && data !== null) {
|
|
3
|
+
return JSON.stringify(data);
|
|
4
|
+
}
|
|
5
|
+
return String(data);
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
const mockDecode = jest.fn((str: string) => {
|
|
9
|
+
try {
|
|
10
|
+
return JSON.parse(str);
|
|
11
|
+
} catch {
|
|
12
|
+
return str;
|
|
13
|
+
}
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
module.exports = {
|
|
17
|
+
encode: mockEncode,
|
|
18
|
+
decode: mockDecode,
|
|
19
|
+
DEFAULT_DELIMITER: ',',
|
|
20
|
+
DELIMITERS: [',', '|', '\t']
|
|
21
|
+
};
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import { AuthNamespace } from '../src/auth';
|
|
2
|
+
import { ApiClient } from '../src/client';
|
|
3
|
+
|
|
4
|
+
jest.mock('../src/client');
|
|
5
|
+
|
|
6
|
+
describe('AuthNamespace', () => {
|
|
7
|
+
let authNamespace: AuthNamespace;
|
|
8
|
+
let mockClient: jest.Mocked<ApiClient>;
|
|
9
|
+
|
|
10
|
+
beforeEach(() => {
|
|
11
|
+
mockClient = {
|
|
12
|
+
get: jest.fn(),
|
|
13
|
+
post: jest.fn(),
|
|
14
|
+
put: jest.fn(),
|
|
15
|
+
delete: jest.fn(),
|
|
16
|
+
setAuthToken: jest.fn(),
|
|
17
|
+
clearAuthToken: jest.fn(),
|
|
18
|
+
setFormat: jest.fn()
|
|
19
|
+
} as any;
|
|
20
|
+
|
|
21
|
+
authNamespace = new AuthNamespace(mockClient);
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
describe('generateKeys', () => {
|
|
25
|
+
it('should generate keys successfully', async () => {
|
|
26
|
+
const mockKeys = {
|
|
27
|
+
publicToken: 'test-public-token',
|
|
28
|
+
privateKey: 'test-private-key'
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
mockClient.post.mockResolvedValue({
|
|
32
|
+
success: true,
|
|
33
|
+
data: mockKeys
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
const result = await authNamespace.generateKeys();
|
|
37
|
+
|
|
38
|
+
expect(result).toEqual(mockKeys);
|
|
39
|
+
expect(mockClient.post).toHaveBeenCalledWith('/v1/auth/generate-keys', {});
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it('should throw error when generation fails', async () => {
|
|
43
|
+
mockClient.post.mockResolvedValue({
|
|
44
|
+
success: false,
|
|
45
|
+
error: { code: 'ERROR', message: 'Generation failed' }
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
await expect(authNamespace.generateKeys()).rejects.toThrow('Generation failed');
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
describe('register', () => {
|
|
53
|
+
it('should register successfully', async () => {
|
|
54
|
+
const mockKeys = {
|
|
55
|
+
publicToken: 'test-public-token',
|
|
56
|
+
privateKey: 'test-private-key'
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
const mockResponse = {
|
|
60
|
+
member: {
|
|
61
|
+
id: 'member-1',
|
|
62
|
+
networkId: 'network-1',
|
|
63
|
+
publicToken: 'test-public-token',
|
|
64
|
+
shortDescription: '',
|
|
65
|
+
longDescription: '',
|
|
66
|
+
role: 'member'
|
|
67
|
+
},
|
|
68
|
+
tokens: {
|
|
69
|
+
jwt: 'test-jwt-token',
|
|
70
|
+
expiresAt: Date.now() + 86400000,
|
|
71
|
+
publicToken: 'test-public-token'
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
mockClient.post.mockResolvedValue({
|
|
76
|
+
success: true,
|
|
77
|
+
data: mockResponse
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
const result = await authNamespace.register('network-1', mockKeys);
|
|
81
|
+
|
|
82
|
+
expect(result).toEqual(mockResponse);
|
|
83
|
+
expect(mockClient.post).toHaveBeenCalledWith('/v1/auth/register', {
|
|
84
|
+
networkId: 'network-1',
|
|
85
|
+
publicToken: 'test-public-token',
|
|
86
|
+
privateKey: 'test-private-key'
|
|
87
|
+
});
|
|
88
|
+
expect(mockClient.setAuthToken).toHaveBeenCalledWith('test-jwt-token');
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
it('should throw error when registration fails', async () => {
|
|
92
|
+
const mockKeys = {
|
|
93
|
+
publicToken: 'test-public-token',
|
|
94
|
+
privateKey: 'test-private-key'
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
mockClient.post.mockResolvedValue({
|
|
98
|
+
success: false,
|
|
99
|
+
error: { code: 'ERROR', message: 'Registration failed' }
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
await expect(authNamespace.register('network-1', mockKeys)).rejects.toThrow('Registration failed');
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
describe('login', () => {
|
|
107
|
+
it('should login successfully', async () => {
|
|
108
|
+
const mockKeys = {
|
|
109
|
+
publicToken: 'test-public-token',
|
|
110
|
+
privateKey: 'test-private-key'
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
const mockTokens = {
|
|
114
|
+
jwt: 'test-jwt-token',
|
|
115
|
+
expiresAt: Date.now() + 86400000,
|
|
116
|
+
publicToken: 'test-public-token'
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
mockClient.post.mockResolvedValue({
|
|
120
|
+
success: true,
|
|
121
|
+
data: mockTokens
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
const result = await authNamespace.login('network-1', mockKeys);
|
|
125
|
+
|
|
126
|
+
expect(result).toEqual(mockTokens);
|
|
127
|
+
expect(mockClient.post).toHaveBeenCalledWith('/v1/auth/login', {
|
|
128
|
+
networkId: 'network-1',
|
|
129
|
+
publicToken: 'test-public-token',
|
|
130
|
+
privateKey: 'test-private-key'
|
|
131
|
+
});
|
|
132
|
+
expect(mockClient.setAuthToken).toHaveBeenCalledWith('test-jwt-token');
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
it('should throw error when login fails', async () => {
|
|
136
|
+
const mockKeys = {
|
|
137
|
+
publicToken: 'test-public-token',
|
|
138
|
+
privateKey: 'test-private-key'
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
mockClient.post.mockResolvedValue({
|
|
142
|
+
success: false,
|
|
143
|
+
error: { code: 'ERROR', message: 'Invalid credentials' }
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
await expect(authNamespace.login('network-1', mockKeys)).rejects.toThrow('Invalid credentials');
|
|
147
|
+
});
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
describe('logout', () => {
|
|
151
|
+
it('should clear auth token', () => {
|
|
152
|
+
authNamespace.logout();
|
|
153
|
+
expect(mockClient.clearAuthToken).toHaveBeenCalled();
|
|
154
|
+
});
|
|
155
|
+
});
|
|
156
|
+
});
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { AgenticPool } from '../src/index';
|
|
2
|
+
import axios from 'axios';
|
|
3
|
+
|
|
4
|
+
jest.mock('axios');
|
|
5
|
+
const mockedAxios = axios as jest.Mocked<typeof axios>;
|
|
6
|
+
|
|
7
|
+
describe('AgenticPool SDK', () => {
|
|
8
|
+
let client: AgenticPool;
|
|
9
|
+
let mockAxiosInstance: any;
|
|
10
|
+
|
|
11
|
+
beforeEach(() => {
|
|
12
|
+
mockAxiosInstance = {
|
|
13
|
+
get: jest.fn(),
|
|
14
|
+
post: jest.fn(),
|
|
15
|
+
put: jest.fn(),
|
|
16
|
+
delete: jest.fn(),
|
|
17
|
+
defaults: {
|
|
18
|
+
headers: {
|
|
19
|
+
common: {},
|
|
20
|
+
'Content-Type': 'application/json',
|
|
21
|
+
Accept: 'text/plain'
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
(mockedAxios.create as jest.Mock).mockReturnValue(mockAxiosInstance);
|
|
27
|
+
client = new AgenticPool();
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
afterEach(() => {
|
|
31
|
+
jest.clearAllMocks();
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
describe('Constructor', () => {
|
|
35
|
+
it('should create instance with default config', () => {
|
|
36
|
+
expect(client).toBeInstanceOf(AgenticPool);
|
|
37
|
+
expect(mockedAxios.create).toHaveBeenCalledWith({
|
|
38
|
+
baseURL: 'https://api.agenticpool.net',
|
|
39
|
+
timeout: 30000,
|
|
40
|
+
headers: {
|
|
41
|
+
'Content-Type': 'application/json',
|
|
42
|
+
Accept: 'text/plain'
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it('should create instance with custom config', () => {
|
|
48
|
+
const customClient = new AgenticPool({
|
|
49
|
+
baseUrl: 'https://custom.api.com',
|
|
50
|
+
timeout: 60000,
|
|
51
|
+
format: 'json'
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
expect(customClient).toBeInstanceOf(AgenticPool);
|
|
55
|
+
expect(mockedAxios.create).toHaveBeenCalledWith({
|
|
56
|
+
baseURL: 'https://custom.api.com',
|
|
57
|
+
timeout: 60000,
|
|
58
|
+
headers: {
|
|
59
|
+
'Content-Type': 'application/json',
|
|
60
|
+
Accept: 'application/json'
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
describe('Namespaces', () => {
|
|
67
|
+
it('should have auth namespace', () => {
|
|
68
|
+
expect(client.auth).toBeDefined();
|
|
69
|
+
expect(typeof client.auth.generateKeys).toBe('function');
|
|
70
|
+
expect(typeof client.auth.register).toBe('function');
|
|
71
|
+
expect(typeof client.auth.login).toBe('function');
|
|
72
|
+
expect(typeof client.auth.logout).toBe('function');
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
it('should have networks namespace', () => {
|
|
76
|
+
expect(client.networks).toBeDefined();
|
|
77
|
+
expect(typeof client.networks.list).toBe('function');
|
|
78
|
+
expect(typeof client.networks.get).toBe('function');
|
|
79
|
+
expect(typeof client.networks.create).toBe('function');
|
|
80
|
+
expect(typeof client.networks.mine).toBe('function');
|
|
81
|
+
expect(typeof client.networks.getMembers).toBe('function');
|
|
82
|
+
expect(typeof client.networks.getQuestions).toBe('function');
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
it('should have conversations namespace', () => {
|
|
86
|
+
expect(client.conversations).toBeDefined();
|
|
87
|
+
expect(typeof client.conversations.list).toBe('function');
|
|
88
|
+
expect(typeof client.conversations.mine).toBe('function');
|
|
89
|
+
expect(typeof client.conversations.create).toBe('function');
|
|
90
|
+
expect(typeof client.conversations.join).toBe('function');
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
it('should have messages namespace', () => {
|
|
94
|
+
expect(client.messages).toBeDefined();
|
|
95
|
+
expect(typeof client.messages.list).toBe('function');
|
|
96
|
+
expect(typeof client.messages.send).toBe('function');
|
|
97
|
+
});
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
describe('Authentication', () => {
|
|
101
|
+
it('should set auth token', () => {
|
|
102
|
+
client.setAuthToken('test-token');
|
|
103
|
+
expect(mockAxiosInstance.defaults.headers.common['Authorization']).toBe('Bearer test-token');
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
it('should clear auth token', () => {
|
|
107
|
+
client.setAuthToken('test-token');
|
|
108
|
+
client.clearAuthToken();
|
|
109
|
+
expect(mockAxiosInstance.defaults.headers.common['Authorization']).toBeUndefined();
|
|
110
|
+
});
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
describe('Format', () => {
|
|
114
|
+
it('should set format to json', () => {
|
|
115
|
+
client.setFormat('json');
|
|
116
|
+
expect(mockAxiosInstance.defaults.headers.Accept).toBe('application/json');
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
it('should set format to toon', () => {
|
|
120
|
+
client.setFormat('toon');
|
|
121
|
+
expect(mockAxiosInstance.defaults.headers.Accept).toBe('text/plain');
|
|
122
|
+
});
|
|
123
|
+
});
|
|
124
|
+
});
|