@bytexbyte/nxtlinq-ai-agent-sdk 1.0.8 → 1.0.9

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.
@@ -1,13 +0,0 @@
1
- import { MetaKeep } from 'metakeep';
2
-
3
- const metakeepClient = new MetaKeep({
4
- appId: 'e7d521f7-3eea-42d7-af42-4d8b962d9a6d',
5
- chainId: 80002,
6
- /* RPC node urls map */
7
- rpcNodeUrls: {
8
- // Update with your node API key
9
- 80002: 'https://rpc-amoy.polygon.technology'
10
- }
11
- });
12
-
13
- export default metakeepClient;
@@ -1,99 +0,0 @@
1
- import { useEffect, useState } from 'react';
2
- import { NxtlinqAITSDK } from '../index';
3
- import { AITInfo, WalletInfo } from '../types/ait-api';
4
-
5
- export function useNxtlinqAIT(sdk: NxtlinqAITSDK) {
6
- const [walletAddress, setWalletAddress] = useState<string | null>(null);
7
- const [walletInfo, setWalletInfo] = useState<WalletInfo | null>(null);
8
- const [ait, setAit] = useState<AITInfo | null>(null);
9
- const [isLoading, setIsLoading] = useState(false);
10
- const [error, setError] = useState<string | null>(null);
11
-
12
- const connectWallet = async () => {
13
- try {
14
- setIsLoading(true);
15
- setError(null);
16
- const address = await sdk.connectWallet();
17
- setWalletAddress(address);
18
- } catch (err) {
19
- setError(err instanceof Error ? err.message : 'Failed to connect wallet');
20
- } finally {
21
- setIsLoading(false);
22
- }
23
- };
24
-
25
- const verifyWallet = async (token: string, method: string) => {
26
- try {
27
- setIsLoading(true);
28
- setError(null);
29
- const info = await sdk.verifyWallet(token, method);
30
- setWalletInfo(info);
31
- return info;
32
- } catch (err) {
33
- setError(err instanceof Error ? err.message : 'Failed to verify wallet');
34
- throw err;
35
- } finally {
36
- setIsLoading(false);
37
- }
38
- };
39
-
40
- const signInWithWallet = async () => {
41
- try {
42
- setIsLoading(true);
43
- setError(null);
44
- const token = await sdk.signInWithWallet();
45
- return token;
46
- } catch (err) {
47
- setError(err instanceof Error ? err.message : 'Failed to sign in with wallet');
48
- throw err;
49
- } finally {
50
- setIsLoading(false);
51
- }
52
- };
53
-
54
- const generateAndRegisterAIT = async (permissions: string[]) => {
55
- try {
56
- setIsLoading(true);
57
- setError(null);
58
- const aitInfo = await sdk.generateAndRegisterAIT(permissions);
59
- setAit(aitInfo);
60
- return aitInfo;
61
- } catch (err) {
62
- setError(err instanceof Error ? err.message : 'Failed to generate AIT');
63
- throw err;
64
- } finally {
65
- setIsLoading(false);
66
- }
67
- };
68
-
69
- useEffect(() => {
70
- const loadData = async () => {
71
- if (walletAddress) {
72
- try {
73
- const [walletInfo, aitInfo] = await Promise.all([
74
- sdk.getWalletInfo(),
75
- sdk.getAIT()
76
- ]);
77
- setWalletInfo(walletInfo);
78
- setAit(aitInfo);
79
- } catch (err) {
80
- console.error('Failed to load wallet info or AIT:', err);
81
- }
82
- }
83
- };
84
-
85
- loadData();
86
- }, [walletAddress, sdk]);
87
-
88
- return {
89
- walletAddress,
90
- walletInfo,
91
- ait,
92
- isLoading,
93
- error,
94
- connectWallet,
95
- verifyWallet,
96
- signInWithWallet,
97
- generateAndRegisterAIT
98
- };
99
- }
package/src/index.ts DELETED
@@ -1,557 +0,0 @@
1
- import { ethers } from 'ethers';
2
- import stringify from 'json-stable-stringify';
3
- import { AITInfo, AITMetadata, PermissionGroup, PermissionOption, WalletInfo, CreateAITParams, CreateMetadataParams, VerifyWalletParams, SignInParams, AITApi } from './types/ait-api';
4
-
5
- const AI_AGENT_API_HOST = 'https://ai-agent.nxtlinq.ai';
6
- const AIT_SERVICE_API_HOST = 'https://staging-ait-service.nxtlinq.ai';
7
-
8
- export const createNxtlinqApi = (apiKey: string, apiSecret: string): AITApi => {
9
- const getAuthHeader = (): Record<string, string> => {
10
- const token = localStorage.getItem('nxtlinqAITServiceAccessToken');
11
- return token ? { 'Authorization': `Bearer ${JSON.parse(token)}` } : {};
12
- };
13
-
14
- return {
15
- ait: {
16
- getAITByServiceIdAndController: async (params: { serviceId: string; controller: string }, token: string) => {
17
- const response = await fetch(`${AIT_SERVICE_API_HOST}/api/ait/service/${params.serviceId}/controller/${params.controller}`, {
18
- method: 'GET',
19
- headers: {
20
- 'X-API-Key': apiKey,
21
- 'X-API-Secret': apiSecret,
22
- ...getAuthHeader()
23
- }
24
- });
25
- return response.json();
26
- },
27
- createAIT: async (params: any, token: string) => {
28
- const response = await fetch(`${AIT_SERVICE_API_HOST}/api/ait`, {
29
- method: 'POST',
30
- headers: {
31
- 'X-API-Key': apiKey,
32
- 'X-API-Secret': apiSecret,
33
- 'Content-Type': 'application/json',
34
- ...getAuthHeader()
35
- },
36
- body: JSON.stringify(params)
37
- });
38
- return response.json();
39
- }
40
- },
41
- wallet: {
42
- verifyWallet: async (params: any, token: string) => {
43
- const response = await fetch(`${AIT_SERVICE_API_HOST}/api/wallet`, {
44
- method: 'POST',
45
- headers: {
46
- 'X-API-Key': apiKey,
47
- 'X-API-Secret': apiSecret,
48
- 'Content-Type': 'application/json',
49
- ...getAuthHeader()
50
- },
51
- body: JSON.stringify(params)
52
- });
53
- return response.json();
54
- },
55
- getWallet: async (params: { address: string }, token: string) => {
56
- const response = await fetch(`${AIT_SERVICE_API_HOST}/api/wallet/address/${params.address}`, {
57
- method: 'GET',
58
- headers: {
59
- 'X-API-Key': apiKey,
60
- 'X-API-Secret': apiSecret,
61
- ...getAuthHeader()
62
- }
63
- });
64
- return response.json();
65
- }
66
- },
67
- metadata: {
68
- createMetadata: async (metadata: any, token: string) => {
69
- const response = await fetch(`${AIT_SERVICE_API_HOST}/api/metadata`, {
70
- method: 'POST',
71
- headers: {
72
- 'X-API-Key': apiKey,
73
- 'X-API-Secret': apiSecret,
74
- 'Content-Type': 'application/json',
75
- ...getAuthHeader()
76
- },
77
- body: JSON.stringify(metadata)
78
- });
79
- return response.json();
80
- }
81
- },
82
- auth: {
83
- getNonce: async (params: { address: string }) => {
84
- const response = await fetch(`${AIT_SERVICE_API_HOST}/api/auth/address/${params.address}/nonce`, {
85
- method: 'GET',
86
- headers: {
87
- 'X-API-Key': apiKey,
88
- 'X-API-Secret': apiSecret,
89
- ...getAuthHeader()
90
- }
91
- });
92
- return response.json();
93
- },
94
- signIn: async (params: any) => {
95
- const response = await fetch(`${AIT_SERVICE_API_HOST}/api/auth`, {
96
- method: 'POST',
97
- headers: {
98
- 'X-API-Key': apiKey,
99
- 'X-API-Secret': apiSecret,
100
- 'Content-Type': 'application/json',
101
- ...getAuthHeader()
102
- },
103
- body: JSON.stringify(params)
104
- });
105
- return response.json();
106
- }
107
- },
108
- agent: {
109
- sendMessage: async (params) => {
110
- try {
111
- const response = await fetch(`${AI_AGENT_API_HOST}/api/agent/message`, {
112
- method: 'POST',
113
- headers: {
114
- 'X-API-Key': apiKey,
115
- 'X-API-Secret': apiSecret,
116
- 'Content-Type': 'application/json',
117
- ...getAuthHeader()
118
- },
119
- body: JSON.stringify(params)
120
- });
121
-
122
- if (!response.ok) {
123
- throw new Error('发送消息失败');
124
- }
125
-
126
- return await response.json();
127
- } catch (error) {
128
- return { error: error instanceof Error ? error.message : '发送消息失败' };
129
- }
130
- }
131
- }
132
- };
133
- };
134
-
135
- export { ChatBot } from './components/ChatBot';
136
- export type { Message, PresetMessage, ToolUse, ChatBotProps } from './components/ChatBot';
137
-
138
- // 导出类型
139
- export type {
140
- AITInfo,
141
- AITMetadata,
142
- PermissionGroup,
143
- PermissionOption,
144
- WalletInfo,
145
- CreateAITParams,
146
- CreateMetadataParams,
147
- VerifyWalletParams,
148
- SignInParams
149
- };
150
-
151
- export interface AITPermission {
152
- hasPermission: boolean;
153
- reason?: string;
154
- permissions?: string[];
155
- }
156
-
157
- export interface AIT {
158
- aitId: string;
159
- controller: string;
160
- metadata: AITMetadata;
161
- metadataHash: string;
162
- metadataCid: string;
163
- signature: string;
164
- }
165
-
166
- export interface GenerateAITOptions {
167
- hitAddress: string;
168
- signer: ethers.Signer;
169
- permissions: string[];
170
- serviceId: string;
171
- }
172
-
173
- export interface MessageResponse {
174
- reply: string;
175
- timestamp: string;
176
- }
177
-
178
- export class NxtlinqAITSDK {
179
- private serviceId: string;
180
- private signer: ethers.Signer | null = null;
181
- private walletAddress: string | null = null;
182
- private api: AITApi;
183
-
184
- constructor(serviceId: string, apiKey: string, apiSecret: string) {
185
- this.serviceId = serviceId;
186
- this.api = createNxtlinqApi(apiKey, apiSecret);
187
- }
188
-
189
- async connectWallet(): Promise<string> {
190
- if (typeof window === 'undefined' || !window.ethereum) {
191
- throw new Error('MetaMask is not installed');
192
- }
193
-
194
- const provider = new ethers.BrowserProvider(window.ethereum);
195
- this.signer = await provider.getSigner();
196
- this.walletAddress = await this.signer.getAddress();
197
- return this.walletAddress;
198
- }
199
-
200
- async verifyWallet(token: string, method: string): Promise<WalletInfo> {
201
- if (!this.walletAddress) {
202
- throw new Error('Please connect wallet first');
203
- }
204
-
205
- const response = await this.api.wallet.verifyWallet({
206
- address: this.walletAddress,
207
- token,
208
- method,
209
- timestamp: Date.now()
210
- }, token);
211
-
212
- if ('error' in response) {
213
- throw new Error(response.error);
214
- }
215
-
216
- return response;
217
- }
218
-
219
- async signInWithWallet(): Promise<string> {
220
- if (!this.walletAddress || !this.signer) {
221
- throw new Error('Please connect wallet first');
222
- }
223
-
224
- const nonceResponse = await this.api.auth.getNonce({ address: this.walletAddress });
225
- if ('error' in nonceResponse) {
226
- throw new Error(nonceResponse.error);
227
- }
228
-
229
- const payload = {
230
- address: this.walletAddress,
231
- code: nonceResponse.code,
232
- timestamp: nonceResponse.timestamp
233
- };
234
-
235
- const stringToSign = stringify(payload);
236
- const signature = await this.signer.signMessage(stringToSign || '');
237
-
238
- const response = await this.api.auth.signIn({
239
- ...payload,
240
- signature
241
- });
242
-
243
- if ('error' in response) {
244
- throw new Error(response.error);
245
- }
246
-
247
- return response.accessToken;
248
- }
249
-
250
- async generateAndRegisterAIT(permissions: string[]): Promise<AITInfo> {
251
- if (!this.signer || !this.walletAddress) {
252
- throw new Error('Please connect wallet first');
253
- }
254
-
255
- const token = localStorage.getItem('nxtlinqAITServiceAccessToken');
256
- if (!token) {
257
- throw new Error('未找到访问令牌');
258
- }
259
-
260
- const timestamp = Math.floor(Date.now() / 1000);
261
- const aitId = `did:polygon:ike-dashboard:${this.walletAddress}:${timestamp}`;
262
-
263
- const metadata: AITMetadata = {
264
- model: 'gpt-4',
265
- permissions,
266
- issuedBy: this.walletAddress
267
- };
268
-
269
- const metadataStr = stringify(metadata);
270
- const metadataHash = ethers.keccak256(ethers.toUtf8Bytes(metadataStr || ''));
271
-
272
- // Upload metadata
273
- const uploadResponse = await this.api.metadata.createMetadata({
274
- ...metadata,
275
- controller: this.walletAddress
276
- }, token);
277
-
278
- if ('error' in uploadResponse) {
279
- throw new Error(`Failed to upload metadata: ${uploadResponse.error}`);
280
- }
281
-
282
- const { metadataCid } = uploadResponse;
283
-
284
- // Sign the message
285
- const messageHash = ethers.solidityPackedKeccak256(
286
- ['string', 'address', 'string', 'bytes32', 'uint256'],
287
- [aitId, this.walletAddress, this.serviceId, metadataHash, timestamp]
288
- );
289
-
290
- const signature = await this.signer.signMessage(ethers.getBytes(messageHash));
291
-
292
- // Register AIT
293
- const response = await this.api.ait.createAIT({
294
- aitId,
295
- controller: this.walletAddress,
296
- serviceId: this.serviceId,
297
- metadataHash,
298
- metadataCid,
299
- timestamp,
300
- signature
301
- }, token);
302
-
303
- if ('error' in response) {
304
- throw new Error(response.error);
305
- }
306
-
307
- return response;
308
- }
309
-
310
- async getAIT(): Promise<AITInfo | null> {
311
- if (!this.walletAddress) {
312
- return null;
313
- }
314
-
315
- const token = localStorage.getItem('nxtlinqAITServiceAccessToken');
316
- if (!token) {
317
- throw new Error('未找到访问令牌');
318
- }
319
-
320
- const response = await this.api.ait.getAITByServiceIdAndController({
321
- serviceId: this.serviceId,
322
- controller: this.walletAddress
323
- }, token);
324
-
325
- if ('error' in response) {
326
- return null;
327
- }
328
-
329
- return response;
330
- }
331
-
332
- async getWalletInfo(): Promise<WalletInfo | null> {
333
- if (!this.walletAddress) {
334
- return null;
335
- }
336
-
337
- const token = localStorage.getItem('nxtlinqAITServiceAccessToken');
338
- if (!token) {
339
- throw new Error('未找到访问令牌');
340
- }
341
-
342
- const response = await this.api.wallet.getWallet({ address: this.walletAddress }, token);
343
- if ('error' in response) {
344
- return null;
345
- }
346
-
347
- return response;
348
- }
349
-
350
- createPermissionForm(permissionGroups: PermissionGroup[]): PermissionGroup[] {
351
- return permissionGroups.map(group => ({
352
- label: group.label,
353
- options: group.options.map((option: PermissionOption) => ({
354
- ...option,
355
- isChecked: false,
356
- }))
357
- }));
358
- }
359
-
360
- getSelectedPermissions(form: PermissionGroup[]): string[] {
361
- return form.flatMap(group =>
362
- group.options.filter((opt: PermissionOption) => opt.isChecked).map((opt: PermissionOption) => opt.value)
363
- );
364
- }
365
- }
366
-
367
- export class NxtlinqAIAgent {
368
- private projectId: string;
369
- private apiKey?: string;
370
- private ait?: AIT;
371
- private permissions: string[] = [];
372
- private signer?: ethers.Signer;
373
- private api: AITApi;
374
-
375
- constructor(projectId: string, apiKey: string, apiSecret: string) {
376
- this.projectId = projectId;
377
- this.apiKey = apiKey;
378
- this.api = createNxtlinqApi(apiKey, apiSecret);
379
- }
380
-
381
- setAIT(ait: AIT, signer?: ethers.Signer) {
382
- this.ait = ait;
383
- this.permissions = ait.metadata.permissions;
384
- if (signer) {
385
- this.signer = signer;
386
- }
387
- }
388
-
389
- private async hasPermission(toolName: string): Promise<boolean> {
390
- if (!this.ait) {
391
- throw new Error('请先连接钱包以访问权限');
392
- }
393
- return this.permissions.includes(toolName);
394
- }
395
-
396
- private async checkAITPermission(toolName?: string): Promise<AITPermission> {
397
- try {
398
- if (!this.ait) {
399
- return {
400
- hasPermission: false,
401
- reason: '请先连接钱包以访问权限'
402
- };
403
- }
404
-
405
- if (!toolName) {
406
- return {
407
- hasPermission: true,
408
- permissions: this.permissions
409
- };
410
- }
411
-
412
- const hasPermission = await this.hasPermission(toolName);
413
- return {
414
- hasPermission,
415
- reason: hasPermission ? undefined : '没有权限使用该工具',
416
- permissions: this.permissions
417
- };
418
- } catch (error) {
419
- return {
420
- hasPermission: false,
421
- reason: error instanceof Error ? error.message : '未知错误',
422
- permissions: this.permissions
423
- };
424
- }
425
- }
426
-
427
- async generateAIT(options: GenerateAITOptions): Promise<AIT> {
428
- const { hitAddress, signer, permissions, serviceId } = options;
429
- const token = localStorage.getItem('nxtlinqAITServiceAccessToken');
430
- if (!token) {
431
- throw new Error('未找到访问令牌');
432
- }
433
-
434
- const timestamp = Math.floor(Date.now() / 1000);
435
- const aitId = `did:polygon:ike-dashboard:${hitAddress}:${timestamp}`;
436
-
437
- const metadata: AITMetadata = {
438
- model: 'gpt-4',
439
- permissions,
440
- issuedBy: hitAddress
441
- };
442
-
443
- const metadataStr = stringify(metadata);
444
- const metadataHash = ethers.keccak256(ethers.toUtf8Bytes(metadataStr || ''));
445
-
446
- // Upload metadata
447
- const uploadResponse = await this.api.metadata.createMetadata({
448
- ...metadata,
449
- controller: hitAddress
450
- }, token);
451
-
452
- if ('error' in uploadResponse) {
453
- throw new Error(`Failed to upload metadata: ${uploadResponse.error}`);
454
- }
455
-
456
- const { metadataCid } = uploadResponse;
457
-
458
- // Sign the message
459
- const messageHash = ethers.solidityPackedKeccak256(
460
- ['string', 'address', 'string', 'bytes32', 'uint256'],
461
- [aitId, hitAddress, serviceId, metadataHash, timestamp]
462
- );
463
-
464
- const signature = await signer.signMessage(ethers.getBytes(messageHash));
465
-
466
- // Register AIT
467
- const response = await this.api.ait.createAIT({
468
- aitId,
469
- controller: hitAddress,
470
- serviceId,
471
- metadataHash,
472
- metadataCid,
473
- timestamp,
474
- signature
475
- }, token);
476
-
477
- if ('error' in response) {
478
- throw new Error(response.error);
479
- }
480
-
481
- return {
482
- aitId: response.aitId,
483
- controller: response.controller,
484
- metadata: response.metadata,
485
- metadataHash: response.metadataHash,
486
- metadataCid: response.metadataCid,
487
- signature: response.signature
488
- };
489
- }
490
-
491
- async getAITInfo(serviceId: string, controller: string, signer?: ethers.Signer): Promise<AIT | null> {
492
- const token = localStorage.getItem('nxtlinqAITServiceAccessToken');
493
- if (!token) {
494
- throw new Error('未找到访问令牌');
495
- }
496
-
497
- const response = await this.api.ait.getAITByServiceIdAndController({
498
- serviceId,
499
- controller
500
- }, token);
501
-
502
- if ('error' in response) {
503
- return null;
504
- }
505
-
506
- if (signer) {
507
- this.signer = signer;
508
- }
509
-
510
- return {
511
- aitId: response.aitId,
512
- controller: response.controller,
513
- metadata: response.metadata,
514
- metadataHash: response.metadataHash,
515
- metadataCid: response.metadataCid,
516
- signature: response.signature
517
- };
518
- }
519
-
520
- async sendMessage(message: string, toolName?: string): Promise<MessageResponse> {
521
- const permission = await this.checkAITPermission(toolName);
522
- if (!permission.hasPermission) {
523
- throw new Error(permission.reason || '没有权限使用该工具');
524
- }
525
-
526
- if (!this.ait || !this.signer) {
527
- throw new Error('请先连接钱包以访问权限');
528
- }
529
-
530
- const timestamp = Math.floor(Date.now() / 1000);
531
- const stringToSign = stringify({
532
- message,
533
- aitId: this.ait.aitId,
534
- controller: this.ait.controller,
535
- metadata: this.ait.metadata,
536
- metadataHash: this.ait.metadataHash,
537
- serviceId: this.projectId,
538
- timestamp
539
- }) || '';
540
-
541
- const signature = await this.signer.signMessage(stringToSign);
542
-
543
- const response = await this.api.agent.sendMessage({
544
- message,
545
- serviceId: this.projectId,
546
- });
547
-
548
- if ('error' in response) {
549
- throw new Error(response.error);
550
- }
551
-
552
- return {
553
- reply: response.reply,
554
- timestamp: new Date().toISOString()
555
- };
556
- }
557
- }