@chainai/core 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/README.md +162 -0
- package/dist/client.d.ts +46 -0
- package/dist/client.js +73 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +19 -0
- package/dist/services/ic-service.d.ts +47 -0
- package/dist/services/ic-service.js +151 -0
- package/dist/services/nlp-service.d.ts +21 -0
- package/dist/services/nlp-service.js +87 -0
- package/dist/types/chat.d.ts +34 -0
- package/dist/types/chat.js +5 -0
- package/dist/types/customization.d.ts +55 -0
- package/dist/types/customization.js +35 -0
- package/dist/types/index.d.ts +20 -0
- package/dist/types/index.js +8 -0
- package/package.json +42 -0
package/README.md
ADDED
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
# @chain-ai/core
|
|
2
|
+
|
|
3
|
+
Core client library for Chain AI - Natural language blockchain assistant powered by the Internet Computer.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @chain-ai/core
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
import { ChainAIClient } from '@chain-ai/core';
|
|
15
|
+
|
|
16
|
+
// Initialize the client with your API key
|
|
17
|
+
const client = new ChainAIClient({
|
|
18
|
+
apiKey: 'sk_dev_123_...',
|
|
19
|
+
host: 'https://icp0.io', // optional
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
// Send a chat message
|
|
23
|
+
const response = await client.chat({
|
|
24
|
+
text: 'What is the price of Bitcoin?',
|
|
25
|
+
conversationId: 'my-conversation-id', // optional
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
console.log(response.data?.response);
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Features
|
|
32
|
+
|
|
33
|
+
- ✅ **API Key Authentication** - Secure usage tracking per developer
|
|
34
|
+
- ✅ **Response Customization** - Personalize AI responses (style, length, templates)
|
|
35
|
+
- ✅ **Streaming Support** - Real-time word-by-word response streaming
|
|
36
|
+
- ✅ **Multi-Chain Support** - Works with BTC, ETH, SOL, ICP
|
|
37
|
+
- ✅ **TypeScript** - Full type safety with TypeScript definitions
|
|
38
|
+
|
|
39
|
+
## API Reference
|
|
40
|
+
|
|
41
|
+
### ChainAIClient
|
|
42
|
+
|
|
43
|
+
#### Constructor
|
|
44
|
+
|
|
45
|
+
```typescript
|
|
46
|
+
new ChainAIClient(config: ChainAIConfig)
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
**Config Options:**
|
|
50
|
+
- `apiKey` (required): Your Chain AI API key
|
|
51
|
+
- `host` (optional): IC host URL (default: 'https://icp0.io')
|
|
52
|
+
- `nlpEdgeCanisterId` (optional): Custom NLP canister ID
|
|
53
|
+
- `developerManagerCanisterId` (optional): Custom developer manager canister ID
|
|
54
|
+
|
|
55
|
+
#### Methods
|
|
56
|
+
|
|
57
|
+
**`validateApiKey()`**
|
|
58
|
+
```typescript
|
|
59
|
+
await client.validateApiKey(): Promise<ValidationResult>
|
|
60
|
+
```
|
|
61
|
+
Validate your API key and get tier information.
|
|
62
|
+
|
|
63
|
+
**`chat(request)`**
|
|
64
|
+
```typescript
|
|
65
|
+
await client.chat({
|
|
66
|
+
text: string,
|
|
67
|
+
conversationId?: string,
|
|
68
|
+
userContext?: any,
|
|
69
|
+
language?: string,
|
|
70
|
+
}): Promise<ChatResponse>
|
|
71
|
+
```
|
|
72
|
+
Send a chat message and get AI response.
|
|
73
|
+
|
|
74
|
+
**`streamChat(request, callbacks)`**
|
|
75
|
+
```typescript
|
|
76
|
+
await client.streamChat(
|
|
77
|
+
{ text: string, ... },
|
|
78
|
+
{
|
|
79
|
+
onChunk?: (chunk: string) => void,
|
|
80
|
+
onDone?: (data: AIResponse) => void,
|
|
81
|
+
onError?: (error: string) => void,
|
|
82
|
+
}
|
|
83
|
+
): Promise<void>
|
|
84
|
+
```
|
|
85
|
+
Stream chat response word-by-word for better UX.
|
|
86
|
+
|
|
87
|
+
**`getCustomization()`**
|
|
88
|
+
```typescript
|
|
89
|
+
await client.getCustomization(): Promise<ResponseCustomization | null>
|
|
90
|
+
```
|
|
91
|
+
Get current response customization settings for your API key.
|
|
92
|
+
|
|
93
|
+
**`updateCustomization(customization)`**
|
|
94
|
+
```typescript
|
|
95
|
+
await client.updateCustomization({
|
|
96
|
+
style?: 'professional' | 'casual' | 'technical' | 'friendly' | 'concise',
|
|
97
|
+
length?: 'short' | 'medium' | 'detailed',
|
|
98
|
+
actionTemplates?: {...},
|
|
99
|
+
dataFormat?: {...},
|
|
100
|
+
}): Promise<{ok: boolean, message?: string}>
|
|
101
|
+
```
|
|
102
|
+
Update response customization settings.
|
|
103
|
+
|
|
104
|
+
**`resetCustomization()`**
|
|
105
|
+
```typescript
|
|
106
|
+
await client.resetCustomization(): Promise<{ok: boolean, message?: string}>
|
|
107
|
+
```
|
|
108
|
+
Reset customization to defaults.
|
|
109
|
+
|
|
110
|
+
## Response Customization
|
|
111
|
+
|
|
112
|
+
Customize how Chain AI responds to queries:
|
|
113
|
+
|
|
114
|
+
### Style Options
|
|
115
|
+
- **professional**: Formal, complete sentences (default)
|
|
116
|
+
- **casual**: Conversational, friendly tone
|
|
117
|
+
- **technical**: Concise, data-focused
|
|
118
|
+
- **friendly**: Enthusiastic language
|
|
119
|
+
- **concise**: Short, minimal responses
|
|
120
|
+
|
|
121
|
+
### Length Options
|
|
122
|
+
- **short**: 1-2 sentences max
|
|
123
|
+
- **medium**: 1 paragraph (default)
|
|
124
|
+
- **detailed**: Multiple paragraphs with context
|
|
125
|
+
|
|
126
|
+
### Example
|
|
127
|
+
|
|
128
|
+
```typescript
|
|
129
|
+
// Set casual, short responses
|
|
130
|
+
await client.updateCustomization({
|
|
131
|
+
style: 'casual',
|
|
132
|
+
length: 'short',
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
// Now responses will be brief and conversational
|
|
136
|
+
const response = await client.chat({
|
|
137
|
+
text: 'Send 0.1 ETH to vitalik.eth',
|
|
138
|
+
});
|
|
139
|
+
// Response: "Done! Transaction sent."
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
## Error Handling
|
|
143
|
+
|
|
144
|
+
```typescript
|
|
145
|
+
try {
|
|
146
|
+
const response = await client.chat({
|
|
147
|
+
text: 'What is the price of Bitcoin?',
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
if (response.ok) {
|
|
151
|
+
console.log(response.data?.response);
|
|
152
|
+
} else {
|
|
153
|
+
console.error('Error:', response.error);
|
|
154
|
+
}
|
|
155
|
+
} catch (error) {
|
|
156
|
+
console.error('Network error:', error);
|
|
157
|
+
}
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
## License
|
|
161
|
+
|
|
162
|
+
MIT
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ChainAIClient - Main client class for interacting with Chain AI
|
|
3
|
+
*/
|
|
4
|
+
import type { ChainAIConfig, ChatRequest, ChatResponse, StreamCallbacks, ValidationResult, ResponseCustomization } from './types';
|
|
5
|
+
export declare class ChainAIClient {
|
|
6
|
+
private icService;
|
|
7
|
+
private nlpService;
|
|
8
|
+
private apiKey;
|
|
9
|
+
private config;
|
|
10
|
+
constructor(config: ChainAIConfig);
|
|
11
|
+
/**
|
|
12
|
+
* Validate the API key
|
|
13
|
+
*/
|
|
14
|
+
validateApiKey(): Promise<ValidationResult>;
|
|
15
|
+
/**
|
|
16
|
+
* Send a chat message and get AI response
|
|
17
|
+
*/
|
|
18
|
+
chat(request: Omit<ChatRequest, 'apiKey'>): Promise<ChatResponse>;
|
|
19
|
+
/**
|
|
20
|
+
* Stream chat response with real-time updates
|
|
21
|
+
*/
|
|
22
|
+
streamChat(request: Omit<ChatRequest, 'apiKey'>, callbacks: StreamCallbacks): Promise<void>;
|
|
23
|
+
/**
|
|
24
|
+
* Get current response customization settings
|
|
25
|
+
*/
|
|
26
|
+
getCustomization(): Promise<ResponseCustomization | null>;
|
|
27
|
+
/**
|
|
28
|
+
* Update response customization settings
|
|
29
|
+
*/
|
|
30
|
+
updateCustomization(customization: Partial<ResponseCustomization>): Promise<{
|
|
31
|
+
ok: boolean;
|
|
32
|
+
message?: string;
|
|
33
|
+
error?: string;
|
|
34
|
+
}>;
|
|
35
|
+
/**
|
|
36
|
+
* Reset customization to defaults
|
|
37
|
+
*/
|
|
38
|
+
resetCustomization(): Promise<{
|
|
39
|
+
ok: boolean;
|
|
40
|
+
message?: string;
|
|
41
|
+
}>;
|
|
42
|
+
/**
|
|
43
|
+
* Check canister health
|
|
44
|
+
*/
|
|
45
|
+
health(): Promise<string>;
|
|
46
|
+
}
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* ChainAIClient - Main client class for interacting with Chain AI
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.ChainAIClient = void 0;
|
|
7
|
+
const ic_service_1 = require("./services/ic-service");
|
|
8
|
+
const nlp_service_1 = require("./services/nlp-service");
|
|
9
|
+
class ChainAIClient {
|
|
10
|
+
constructor(config) {
|
|
11
|
+
this.config = config;
|
|
12
|
+
this.apiKey = config.apiKey;
|
|
13
|
+
// Initialize IC service
|
|
14
|
+
this.icService = new ic_service_1.ICService({
|
|
15
|
+
host: config.host || 'https://icp0.io',
|
|
16
|
+
nlpEdgeCanisterId: config.nlpEdgeCanisterId || 'ypzdi-iqaaa-aaaam-qfhla-cai',
|
|
17
|
+
developerManagerCanisterId: config.developerManagerCanisterId || 'yiyf4-fiaaa-aaaam-qfhlq-cai',
|
|
18
|
+
});
|
|
19
|
+
// Initialize NLP service
|
|
20
|
+
this.nlpService = new nlp_service_1.NLPService(this.icService);
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Validate the API key
|
|
24
|
+
*/
|
|
25
|
+
async validateApiKey() {
|
|
26
|
+
return this.icService.validateApiKey(this.apiKey);
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Send a chat message and get AI response
|
|
30
|
+
*/
|
|
31
|
+
async chat(request) {
|
|
32
|
+
const fullRequest = {
|
|
33
|
+
...request,
|
|
34
|
+
apiKey: this.apiKey,
|
|
35
|
+
};
|
|
36
|
+
return this.nlpService.chat(fullRequest);
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Stream chat response with real-time updates
|
|
40
|
+
*/
|
|
41
|
+
async streamChat(request, callbacks) {
|
|
42
|
+
const fullRequest = {
|
|
43
|
+
...request,
|
|
44
|
+
apiKey: this.apiKey,
|
|
45
|
+
};
|
|
46
|
+
return this.nlpService.streamChat(fullRequest, callbacks);
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Get current response customization settings
|
|
50
|
+
*/
|
|
51
|
+
async getCustomization() {
|
|
52
|
+
return this.icService.getResponseCustomization(this.apiKey);
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Update response customization settings
|
|
56
|
+
*/
|
|
57
|
+
async updateCustomization(customization) {
|
|
58
|
+
return this.icService.setResponseCustomization(this.apiKey, customization);
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Reset customization to defaults
|
|
62
|
+
*/
|
|
63
|
+
async resetCustomization() {
|
|
64
|
+
return this.icService.deleteResponseCustomization(this.apiKey);
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Check canister health
|
|
68
|
+
*/
|
|
69
|
+
async health() {
|
|
70
|
+
return this.nlpService.health();
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
exports.ChainAIClient = ChainAIClient;
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @chain-ai/core - Core client library for Chain AI
|
|
3
|
+
*
|
|
4
|
+
* Natural language blockchain assistant powered by the Internet Computer
|
|
5
|
+
*/
|
|
6
|
+
export { ChainAIClient } from './client';
|
|
7
|
+
export { ICService } from './services/ic-service';
|
|
8
|
+
export { NLPService } from './services/nlp-service';
|
|
9
|
+
export type { ChainAIConfig, ValidationResult, ResponseCustomization, ResponseStyle, ResponseLength, ActionTemplates, DataFormatOptions, DateFormat, AddressFormat, NumberFormat, ChatRequest, ChatResponse, AIResponse, Message, StreamCallbacks, } from './types';
|
|
10
|
+
export { DEFAULT_CUSTOMIZATION } from './types';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @chain-ai/core - Core client library for Chain AI
|
|
4
|
+
*
|
|
5
|
+
* Natural language blockchain assistant powered by the Internet Computer
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.DEFAULT_CUSTOMIZATION = exports.NLPService = exports.ICService = exports.ChainAIClient = void 0;
|
|
9
|
+
// Main client export
|
|
10
|
+
var client_1 = require("./client");
|
|
11
|
+
Object.defineProperty(exports, "ChainAIClient", { enumerable: true, get: function () { return client_1.ChainAIClient; } });
|
|
12
|
+
// Service exports
|
|
13
|
+
var ic_service_1 = require("./services/ic-service");
|
|
14
|
+
Object.defineProperty(exports, "ICService", { enumerable: true, get: function () { return ic_service_1.ICService; } });
|
|
15
|
+
var nlp_service_1 = require("./services/nlp-service");
|
|
16
|
+
Object.defineProperty(exports, "NLPService", { enumerable: true, get: function () { return nlp_service_1.NLPService; } });
|
|
17
|
+
// Constants
|
|
18
|
+
var types_1 = require("./types");
|
|
19
|
+
Object.defineProperty(exports, "DEFAULT_CUSTOMIZATION", { enumerable: true, get: function () { return types_1.DEFAULT_CUSTOMIZATION; } });
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* IC Service - Manages connections to Internet Computer canisters
|
|
3
|
+
*/
|
|
4
|
+
import type { ValidationResult, ResponseCustomization } from '../types';
|
|
5
|
+
export interface ICServiceConfig {
|
|
6
|
+
host: string;
|
|
7
|
+
nlpEdgeCanisterId: string;
|
|
8
|
+
developerManagerCanisterId: string;
|
|
9
|
+
}
|
|
10
|
+
export declare class ICService {
|
|
11
|
+
private agent;
|
|
12
|
+
private nlpEdgeActor;
|
|
13
|
+
private developerManagerActor;
|
|
14
|
+
private config;
|
|
15
|
+
constructor(config: ICServiceConfig);
|
|
16
|
+
/**
|
|
17
|
+
* Validate an API key with the developer_manager canister
|
|
18
|
+
*/
|
|
19
|
+
validateApiKey(apiKey: string): Promise<ValidationResult>;
|
|
20
|
+
/**
|
|
21
|
+
* Get response customization for an API key
|
|
22
|
+
*/
|
|
23
|
+
getResponseCustomization(apiKey: string): Promise<ResponseCustomization | null>;
|
|
24
|
+
/**
|
|
25
|
+
* Set response customization for an API key
|
|
26
|
+
*/
|
|
27
|
+
setResponseCustomization(apiKey: string, customization: Partial<ResponseCustomization>): Promise<{
|
|
28
|
+
ok: boolean;
|
|
29
|
+
message?: string;
|
|
30
|
+
error?: string;
|
|
31
|
+
}>;
|
|
32
|
+
/**
|
|
33
|
+
* Delete response customization (reset to defaults)
|
|
34
|
+
*/
|
|
35
|
+
deleteResponseCustomization(apiKey: string): Promise<{
|
|
36
|
+
ok: boolean;
|
|
37
|
+
message?: string;
|
|
38
|
+
}>;
|
|
39
|
+
/**
|
|
40
|
+
* Get the NLP Edge actor for direct canister calls
|
|
41
|
+
*/
|
|
42
|
+
getNLPEdgeActor(): any;
|
|
43
|
+
/**
|
|
44
|
+
* Get the Developer Manager actor for direct canister calls
|
|
45
|
+
*/
|
|
46
|
+
getDeveloperManagerActor(): any;
|
|
47
|
+
}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* IC Service - Manages connections to Internet Computer canisters
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.ICService = void 0;
|
|
7
|
+
const agent_1 = require("@dfinity/agent");
|
|
8
|
+
const principal_1 = require("@dfinity/principal");
|
|
9
|
+
// IDL factory for NLP Edge canister
|
|
10
|
+
const createNLPEdgeIdl = (idlFactory) => {
|
|
11
|
+
const { IDL } = idlFactory;
|
|
12
|
+
return IDL.Service({
|
|
13
|
+
'chat': IDL.Func([IDL.Record({
|
|
14
|
+
'message': IDL.Text,
|
|
15
|
+
'conversationId': IDL.Text,
|
|
16
|
+
'language': IDL.Opt(IDL.Text),
|
|
17
|
+
'userContext': IDL.Opt(IDL.Text),
|
|
18
|
+
'apiKey': IDL.Opt(IDL.Text),
|
|
19
|
+
})], [IDL.Text], []),
|
|
20
|
+
'health': IDL.Func([], [IDL.Text], ['query']),
|
|
21
|
+
});
|
|
22
|
+
};
|
|
23
|
+
// IDL factory for Developer Manager canister
|
|
24
|
+
const createDeveloperManagerIdl = (idlFactory) => {
|
|
25
|
+
const { IDL } = idlFactory;
|
|
26
|
+
return IDL.Service({
|
|
27
|
+
'validateApiKey': IDL.Func([IDL.Text], [IDL.Text], ['query']),
|
|
28
|
+
'getResponseCustomization': IDL.Func([IDL.Text], [IDL.Text], ['query']),
|
|
29
|
+
'setResponseCustomization': IDL.Func([IDL.Text, IDL.Text, IDL.Text, IDL.Text, IDL.Text, IDL.Text, IDL.Text], [IDL.Text], []),
|
|
30
|
+
'deleteResponseCustomization': IDL.Func([IDL.Text], [IDL.Text], []),
|
|
31
|
+
'recordUsage': IDL.Func([IDL.Text], [], []),
|
|
32
|
+
});
|
|
33
|
+
};
|
|
34
|
+
class ICService {
|
|
35
|
+
constructor(config) {
|
|
36
|
+
this.config = config;
|
|
37
|
+
this.agent = new agent_1.HttpAgent({ host: config.host });
|
|
38
|
+
// For local development, fetch root key
|
|
39
|
+
if (config.host.includes('localhost') || config.host.includes('127.0.0.1')) {
|
|
40
|
+
this.agent.fetchRootKey().catch(console.warn);
|
|
41
|
+
}
|
|
42
|
+
// Create actors (using simplified IDL for now)
|
|
43
|
+
this.nlpEdgeActor = agent_1.Actor.createActor(createNLPEdgeIdl, {
|
|
44
|
+
agent: this.agent,
|
|
45
|
+
canisterId: principal_1.Principal.fromText(config.nlpEdgeCanisterId),
|
|
46
|
+
});
|
|
47
|
+
this.developerManagerActor = agent_1.Actor.createActor(createDeveloperManagerIdl, {
|
|
48
|
+
agent: this.agent,
|
|
49
|
+
canisterId: principal_1.Principal.fromText(config.developerManagerCanisterId),
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Validate an API key with the developer_manager canister
|
|
54
|
+
*/
|
|
55
|
+
async validateApiKey(apiKey) {
|
|
56
|
+
try {
|
|
57
|
+
const result = await this.developerManagerActor.validateApiKey(apiKey);
|
|
58
|
+
const parsed = JSON.parse(result);
|
|
59
|
+
if (parsed.ok) {
|
|
60
|
+
return {
|
|
61
|
+
ok: true,
|
|
62
|
+
developerId: parsed.developerId,
|
|
63
|
+
tier: parsed.tier,
|
|
64
|
+
rateLimit: parsed.rateLimit,
|
|
65
|
+
hasCustomization: parsed.hasCustomization || false,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
return {
|
|
70
|
+
ok: false,
|
|
71
|
+
error: parsed.error,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
catch (error) {
|
|
76
|
+
return {
|
|
77
|
+
ok: false,
|
|
78
|
+
error: error instanceof Error ? error.message : 'Unknown error',
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Get response customization for an API key
|
|
84
|
+
*/
|
|
85
|
+
async getResponseCustomization(apiKey) {
|
|
86
|
+
try {
|
|
87
|
+
const result = await this.developerManagerActor.getResponseCustomization(apiKey);
|
|
88
|
+
const parsed = JSON.parse(result);
|
|
89
|
+
if (parsed.ok && parsed.customization) {
|
|
90
|
+
return {
|
|
91
|
+
apiKey,
|
|
92
|
+
...parsed.customization,
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
catch (error) {
|
|
98
|
+
console.error('Error fetching customization:', error);
|
|
99
|
+
return null;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Set response customization for an API key
|
|
104
|
+
*/
|
|
105
|
+
async setResponseCustomization(apiKey, customization) {
|
|
106
|
+
try {
|
|
107
|
+
const styleText = customization.style || 'professional';
|
|
108
|
+
const lengthText = customization.length || 'medium';
|
|
109
|
+
const responseFormatText = customization.responseFormat || 'text';
|
|
110
|
+
const actionTemplatesJson = JSON.stringify(customization.actionTemplates || {});
|
|
111
|
+
const actionSchemasJson = JSON.stringify(customization.actionSchemas || {});
|
|
112
|
+
const dataFormatJson = JSON.stringify(customization.dataFormat || {});
|
|
113
|
+
const result = await this.developerManagerActor.setResponseCustomization(apiKey, styleText, lengthText, responseFormatText, actionTemplatesJson, actionSchemasJson, dataFormatJson);
|
|
114
|
+
return JSON.parse(result);
|
|
115
|
+
}
|
|
116
|
+
catch (error) {
|
|
117
|
+
return {
|
|
118
|
+
ok: false,
|
|
119
|
+
error: error instanceof Error ? error.message : 'Unknown error',
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Delete response customization (reset to defaults)
|
|
125
|
+
*/
|
|
126
|
+
async deleteResponseCustomization(apiKey) {
|
|
127
|
+
try {
|
|
128
|
+
const result = await this.developerManagerActor.deleteResponseCustomization(apiKey);
|
|
129
|
+
return JSON.parse(result);
|
|
130
|
+
}
|
|
131
|
+
catch (error) {
|
|
132
|
+
return {
|
|
133
|
+
ok: false,
|
|
134
|
+
message: error instanceof Error ? error.message : 'Unknown error',
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Get the NLP Edge actor for direct canister calls
|
|
140
|
+
*/
|
|
141
|
+
getNLPEdgeActor() {
|
|
142
|
+
return this.nlpEdgeActor;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Get the Developer Manager actor for direct canister calls
|
|
146
|
+
*/
|
|
147
|
+
getDeveloperManagerActor() {
|
|
148
|
+
return this.developerManagerActor;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
exports.ICService = ICService;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* NLP Service - Handles chat requests and streaming responses
|
|
3
|
+
*/
|
|
4
|
+
import type { ICService } from './ic-service';
|
|
5
|
+
import type { ChatRequest, ChatResponse, StreamCallbacks } from '../types';
|
|
6
|
+
export declare class NLPService {
|
|
7
|
+
private icService;
|
|
8
|
+
constructor(icService: ICService);
|
|
9
|
+
/**
|
|
10
|
+
* Send a chat message and get AI response
|
|
11
|
+
*/
|
|
12
|
+
chat(request: ChatRequest): Promise<ChatResponse>;
|
|
13
|
+
/**
|
|
14
|
+
* Stream chat response word-by-word for better UX
|
|
15
|
+
*/
|
|
16
|
+
streamChat(request: ChatRequest, callbacks: StreamCallbacks): Promise<void>;
|
|
17
|
+
/**
|
|
18
|
+
* Check canister health
|
|
19
|
+
*/
|
|
20
|
+
health(): Promise<string>;
|
|
21
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* NLP Service - Handles chat requests and streaming responses
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.NLPService = void 0;
|
|
7
|
+
class NLPService {
|
|
8
|
+
constructor(icService) {
|
|
9
|
+
this.icService = icService;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Send a chat message and get AI response
|
|
13
|
+
*/
|
|
14
|
+
async chat(request) {
|
|
15
|
+
const actor = this.icService.getNLPEdgeActor();
|
|
16
|
+
const chatRequest = {
|
|
17
|
+
message: request.text,
|
|
18
|
+
conversationId: request.conversationId || '',
|
|
19
|
+
language: request.language ? [request.language] : [],
|
|
20
|
+
userContext: request.userContext ? [JSON.stringify(request.userContext)] : [],
|
|
21
|
+
apiKey: request.apiKey ? [request.apiKey] : [],
|
|
22
|
+
};
|
|
23
|
+
try {
|
|
24
|
+
const result = await actor.chat(chatRequest);
|
|
25
|
+
if (result.ok) {
|
|
26
|
+
return {
|
|
27
|
+
ok: true,
|
|
28
|
+
data: {
|
|
29
|
+
response: result.ok.response,
|
|
30
|
+
intent: result.ok.intent,
|
|
31
|
+
kind: result.ok.kind,
|
|
32
|
+
toolData: result.ok.toolData,
|
|
33
|
+
confidence: result.ok.confidence,
|
|
34
|
+
conversationId: result.ok.conversationId,
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
return {
|
|
40
|
+
ok: false,
|
|
41
|
+
error: result.err,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
catch (error) {
|
|
46
|
+
return {
|
|
47
|
+
ok: false,
|
|
48
|
+
error: error instanceof Error ? error.message : 'Unknown error',
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Stream chat response word-by-word for better UX
|
|
54
|
+
*/
|
|
55
|
+
async streamChat(request, callbacks) {
|
|
56
|
+
try {
|
|
57
|
+
// Send start event
|
|
58
|
+
callbacks.onChunk?.('');
|
|
59
|
+
const result = await this.chat(request);
|
|
60
|
+
if (result.ok && result.data) {
|
|
61
|
+
const response = result.data.response;
|
|
62
|
+
// Stream response word-by-word with 15ms delay
|
|
63
|
+
const words = response.split(' ');
|
|
64
|
+
for (let i = 0; i < words.length; i++) {
|
|
65
|
+
const chunk = words[i] + (i < words.length - 1 ? ' ' : '');
|
|
66
|
+
callbacks.onChunk?.(chunk);
|
|
67
|
+
await new Promise(resolve => setTimeout(resolve, 15));
|
|
68
|
+
}
|
|
69
|
+
callbacks.onDone?.(result.data);
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
callbacks.onError?.(result.error || 'An error occurred');
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
catch (error) {
|
|
76
|
+
callbacks.onError?.(error instanceof Error ? error.message : 'Unknown error');
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Check canister health
|
|
81
|
+
*/
|
|
82
|
+
async health() {
|
|
83
|
+
const actor = this.icService.getNLPEdgeActor();
|
|
84
|
+
return await actor.health();
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
exports.NLPService = NLPService;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Chat request and response types for Chain AI
|
|
3
|
+
*/
|
|
4
|
+
export interface ChatRequest {
|
|
5
|
+
text: string;
|
|
6
|
+
conversationId?: string;
|
|
7
|
+
userContext?: any;
|
|
8
|
+
language?: string;
|
|
9
|
+
apiKey?: string;
|
|
10
|
+
}
|
|
11
|
+
export interface AIResponse {
|
|
12
|
+
response: string;
|
|
13
|
+
intent: string;
|
|
14
|
+
kind: string;
|
|
15
|
+
toolData: string;
|
|
16
|
+
confidence: number;
|
|
17
|
+
conversationId: string;
|
|
18
|
+
}
|
|
19
|
+
export interface ChatResponse {
|
|
20
|
+
ok: boolean;
|
|
21
|
+
data?: AIResponse;
|
|
22
|
+
error?: string;
|
|
23
|
+
}
|
|
24
|
+
export interface Message {
|
|
25
|
+
id: string;
|
|
26
|
+
role: 'user' | 'assistant';
|
|
27
|
+
content: string;
|
|
28
|
+
timestamp: number;
|
|
29
|
+
}
|
|
30
|
+
export interface StreamCallbacks {
|
|
31
|
+
onChunk?: (chunk: string) => void;
|
|
32
|
+
onDone?: (data: AIResponse) => void;
|
|
33
|
+
onError?: (error: string) => void;
|
|
34
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Response customization types for Chain AI
|
|
3
|
+
* Allows per-API-key customization of AI responses
|
|
4
|
+
*/
|
|
5
|
+
export type ResponseStyle = 'professional' | 'casual' | 'technical' | 'friendly' | 'concise';
|
|
6
|
+
export type ResponseLength = 'short' | 'medium' | 'detailed';
|
|
7
|
+
export type ResponseFormat = 'text' | 'json' | 'hybrid';
|
|
8
|
+
export type DateFormat = 'relative' | 'absolute' | 'both';
|
|
9
|
+
export type AddressFormat = 'full' | 'truncated' | 'ens';
|
|
10
|
+
export type NumberFormat = 'us' | 'eu' | 'scientific';
|
|
11
|
+
export interface ActionSchema {
|
|
12
|
+
required: string[];
|
|
13
|
+
optional?: string[];
|
|
14
|
+
inferRules?: {
|
|
15
|
+
[field: string]: string;
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
export interface ActionSchemas {
|
|
19
|
+
send?: ActionSchema;
|
|
20
|
+
swap?: ActionSchema;
|
|
21
|
+
approve?: ActionSchema;
|
|
22
|
+
transfer?: ActionSchema;
|
|
23
|
+
stake?: ActionSchema;
|
|
24
|
+
[key: string]: ActionSchema | undefined;
|
|
25
|
+
}
|
|
26
|
+
export interface ActionTemplates {
|
|
27
|
+
send?: string;
|
|
28
|
+
swap?: string;
|
|
29
|
+
approve?: string;
|
|
30
|
+
price?: string;
|
|
31
|
+
balance?: string;
|
|
32
|
+
fees?: string;
|
|
33
|
+
transaction_status?: string;
|
|
34
|
+
transaction_history?: string;
|
|
35
|
+
}
|
|
36
|
+
export interface DataFormatOptions {
|
|
37
|
+
priceDecimals: number;
|
|
38
|
+
showUsdEquivalent: boolean;
|
|
39
|
+
dateFormat: DateFormat;
|
|
40
|
+
addressDisplay: AddressFormat;
|
|
41
|
+
numberFormat: NumberFormat;
|
|
42
|
+
}
|
|
43
|
+
export interface ResponseCustomization {
|
|
44
|
+
apiKey: string;
|
|
45
|
+
style: ResponseStyle;
|
|
46
|
+
length: ResponseLength;
|
|
47
|
+
responseFormat: ResponseFormat;
|
|
48
|
+
actionTemplates: ActionTemplates;
|
|
49
|
+
actionSchemas?: ActionSchemas;
|
|
50
|
+
dataFormat: DataFormatOptions;
|
|
51
|
+
createdAt: number;
|
|
52
|
+
updatedAt: number;
|
|
53
|
+
}
|
|
54
|
+
export declare const DEFAULT_ACTION_SCHEMAS: ActionSchemas;
|
|
55
|
+
export declare const DEFAULT_CUSTOMIZATION: Omit<ResponseCustomization, 'apiKey' | 'createdAt' | 'updatedAt'>;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Response customization types for Chain AI
|
|
4
|
+
* Allows per-API-key customization of AI responses
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.DEFAULT_CUSTOMIZATION = exports.DEFAULT_ACTION_SCHEMAS = void 0;
|
|
8
|
+
// Example action schema for common wallet operations
|
|
9
|
+
exports.DEFAULT_ACTION_SCHEMAS = {
|
|
10
|
+
send: {
|
|
11
|
+
required: ['amount', 'currency', 'address'],
|
|
12
|
+
optional: ['fee', 'memo'],
|
|
13
|
+
inferRules: {
|
|
14
|
+
chain: 'Infer from address format (e.g., bc1q... = Bitcoin, 0x... = Ethereum)',
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
swap: {
|
|
18
|
+
required: ['fromCurrency', 'toCurrency', 'amount'],
|
|
19
|
+
optional: ['slippage', 'deadline'],
|
|
20
|
+
},
|
|
21
|
+
};
|
|
22
|
+
exports.DEFAULT_CUSTOMIZATION = {
|
|
23
|
+
style: 'professional',
|
|
24
|
+
length: 'medium',
|
|
25
|
+
responseFormat: 'text',
|
|
26
|
+
actionTemplates: {},
|
|
27
|
+
actionSchemas: undefined, // Wallet providers can define their own
|
|
28
|
+
dataFormat: {
|
|
29
|
+
priceDecimals: 2,
|
|
30
|
+
showUsdEquivalent: true,
|
|
31
|
+
dateFormat: 'relative',
|
|
32
|
+
addressDisplay: 'truncated',
|
|
33
|
+
numberFormat: 'us',
|
|
34
|
+
},
|
|
35
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Main types export for @chain-ai/core
|
|
3
|
+
*/
|
|
4
|
+
export type { ResponseCustomization, ResponseStyle, ResponseLength, ActionTemplates, DataFormatOptions, DateFormat, AddressFormat, NumberFormat, } from './customization';
|
|
5
|
+
export { DEFAULT_CUSTOMIZATION } from './customization';
|
|
6
|
+
export type { ChatRequest, ChatResponse, AIResponse, Message, StreamCallbacks, } from './chat';
|
|
7
|
+
export interface ChainAIConfig {
|
|
8
|
+
apiKey: string;
|
|
9
|
+
host?: string;
|
|
10
|
+
nlpEdgeCanisterId?: string;
|
|
11
|
+
developerManagerCanisterId?: string;
|
|
12
|
+
}
|
|
13
|
+
export interface ValidationResult {
|
|
14
|
+
ok: boolean;
|
|
15
|
+
developerId?: string;
|
|
16
|
+
tier?: string;
|
|
17
|
+
rateLimit?: number;
|
|
18
|
+
hasCustomization?: boolean;
|
|
19
|
+
error?: string;
|
|
20
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Main types export for @chain-ai/core
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.DEFAULT_CUSTOMIZATION = void 0;
|
|
7
|
+
var customization_1 = require("./customization");
|
|
8
|
+
Object.defineProperty(exports, "DEFAULT_CUSTOMIZATION", { enumerable: true, get: function () { return customization_1.DEFAULT_CUSTOMIZATION; } });
|
package/package.json
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@chainai/core",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Core client library for Chain AI - Natural language blockchain assistant",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"module": "dist/index.esm.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"files": [
|
|
9
|
+
"dist"
|
|
10
|
+
],
|
|
11
|
+
"scripts": {
|
|
12
|
+
"build": "tsc",
|
|
13
|
+
"dev": "tsc --watch",
|
|
14
|
+
"test": "jest",
|
|
15
|
+
"lint": "eslint src --ext .ts",
|
|
16
|
+
"type-check": "tsc --noEmit"
|
|
17
|
+
},
|
|
18
|
+
"keywords": [
|
|
19
|
+
"blockchain",
|
|
20
|
+
"ai",
|
|
21
|
+
"nlp",
|
|
22
|
+
"crypto",
|
|
23
|
+
"icp",
|
|
24
|
+
"internet-computer",
|
|
25
|
+
"chain-ai"
|
|
26
|
+
],
|
|
27
|
+
"author": "Chain AI",
|
|
28
|
+
"license": "MIT",
|
|
29
|
+
"dependencies": {
|
|
30
|
+
"@dfinity/agent": "^3.4.3",
|
|
31
|
+
"@dfinity/candid": "^3.4.3",
|
|
32
|
+
"@dfinity/principal": "^3.4.3"
|
|
33
|
+
},
|
|
34
|
+
"devDependencies": {
|
|
35
|
+
"@types/node": "^20.11.0",
|
|
36
|
+
"typescript": "^5.4.5"
|
|
37
|
+
},
|
|
38
|
+
"repository": {
|
|
39
|
+
"type": "git",
|
|
40
|
+
"url": "https://github.com/chain-ai/npm-packages.git"
|
|
41
|
+
}
|
|
42
|
+
}
|