@chainai/core 1.0.4 → 1.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/dist/index.js CHANGED
@@ -1,19 +1,238 @@
1
- "use strict";
2
- /**
3
- * @chainai/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; } });
1
+ // src/stream.ts
2
+ async function* parseSSEStream(body) {
3
+ const reader = body.getReader();
4
+ const decoder = new TextDecoder();
5
+ let buffer = "";
6
+ try {
7
+ while (true) {
8
+ const { done, value } = await reader.read();
9
+ if (done) break;
10
+ buffer += decoder.decode(value, { stream: true });
11
+ const parts = buffer.split("\n\n");
12
+ buffer = parts.pop() || "";
13
+ for (const part of parts) {
14
+ const lines = part.split("\n");
15
+ let eventType = "";
16
+ const dataLines = [];
17
+ for (const line of lines) {
18
+ if (line.startsWith("event: ")) {
19
+ eventType = line.slice(7).trim();
20
+ } else if (line.startsWith("data: ")) {
21
+ dataLines.push(line.slice(6));
22
+ }
23
+ }
24
+ if (eventType && dataLines.length > 0) {
25
+ yield {
26
+ event: eventType,
27
+ data: dataLines.join("\n")
28
+ };
29
+ }
30
+ }
31
+ }
32
+ } finally {
33
+ reader.releaseLock();
34
+ }
35
+ }
36
+ function dispatchSSEEvent(event, callbacks) {
37
+ const { event: eventType, data } = event;
38
+ switch (eventType) {
39
+ case "text":
40
+ callbacks.onText?.(data);
41
+ break;
42
+ case "tool_call":
43
+ try {
44
+ const parsed = JSON.parse(data);
45
+ callbacks.onToolCall?.(parsed.name, parsed.input || {});
46
+ } catch {
47
+ }
48
+ break;
49
+ case "tool_done":
50
+ try {
51
+ const parsed = JSON.parse(data);
52
+ callbacks.onToolDone?.(parsed.name, parsed.success ?? true);
53
+ } catch {
54
+ }
55
+ break;
56
+ case "transaction":
57
+ try {
58
+ callbacks.onTransaction?.(JSON.parse(data));
59
+ } catch {
60
+ }
61
+ break;
62
+ case "chart":
63
+ try {
64
+ callbacks.onChart?.(JSON.parse(data));
65
+ } catch {
66
+ }
67
+ break;
68
+ case "sign_typed_data":
69
+ try {
70
+ callbacks.onSignRequest?.(
71
+ JSON.parse(data)
72
+ );
73
+ } catch {
74
+ }
75
+ break;
76
+ case "hl_deposit":
77
+ try {
78
+ callbacks.onDepositRequest?.(
79
+ JSON.parse(data)
80
+ );
81
+ } catch {
82
+ }
83
+ break;
84
+ case "moonpay_onramp":
85
+ try {
86
+ callbacks.onOnrampRequest?.(JSON.parse(data));
87
+ } catch {
88
+ }
89
+ break;
90
+ case "error":
91
+ callbacks.onError?.(data);
92
+ break;
93
+ case "done":
94
+ try {
95
+ callbacks.onDone?.(JSON.parse(data));
96
+ } catch {
97
+ callbacks.onDone?.({ conversationId: "" });
98
+ }
99
+ break;
100
+ }
101
+ }
102
+
103
+ // src/client.ts
104
+ var DEFAULT_BASE_URL = "http://localhost:3000";
105
+ var ChainAIClient = class {
106
+ apiKey;
107
+ baseUrl;
108
+ constructor(config) {
109
+ if (!config.apiKey) {
110
+ throw new Error("ChainAIClient requires an apiKey");
111
+ }
112
+ this.apiKey = config.apiKey;
113
+ this.baseUrl = (config.baseUrl || DEFAULT_BASE_URL).replace(/\/+$/, "");
114
+ }
115
+ headers(json = false) {
116
+ const h = {
117
+ "X-API-Key": this.apiKey
118
+ };
119
+ if (json) h["Content-Type"] = "application/json";
120
+ return h;
121
+ }
122
+ // ===== Non-streaming Chat =====
123
+ async chat(message, options) {
124
+ const res = await fetch(`${this.baseUrl}/chat`, {
125
+ method: "POST",
126
+ headers: this.headers(true),
127
+ body: JSON.stringify({
128
+ message,
129
+ conversationId: options?.conversationId,
130
+ walletContext: options?.walletContext,
131
+ walletAddress: options?.walletAddress
132
+ })
133
+ });
134
+ if (!res.ok) {
135
+ const err = await res.json().catch(() => ({ error: res.statusText }));
136
+ throw new Error(
137
+ err.error || `API error: ${res.status}`
138
+ );
139
+ }
140
+ return res.json();
141
+ }
142
+ // ===== Streaming Chat =====
143
+ async chatStream(message, options, callbacks) {
144
+ const controller = new AbortController();
145
+ const res = await fetch(`${this.baseUrl}/chat/stream`, {
146
+ method: "POST",
147
+ headers: this.headers(true),
148
+ body: JSON.stringify({
149
+ message,
150
+ conversationId: options?.conversationId,
151
+ walletContext: options?.walletContext,
152
+ walletAddress: options?.walletAddress
153
+ }),
154
+ signal: controller.signal
155
+ });
156
+ if (!res.ok) {
157
+ const err = await res.json().catch(() => ({ error: res.statusText }));
158
+ throw new Error(
159
+ err.error || `API error: ${res.status}`
160
+ );
161
+ }
162
+ if (!res.body) {
163
+ throw new Error("No response body");
164
+ }
165
+ const process = async () => {
166
+ try {
167
+ for await (const event of parseSSEStream(res.body)) {
168
+ if (callbacks) {
169
+ dispatchSSEEvent(event, callbacks);
170
+ }
171
+ }
172
+ } catch (err) {
173
+ if (err.name !== "AbortError") {
174
+ callbacks?.onError?.(
175
+ err instanceof Error ? err.message : String(err)
176
+ );
177
+ }
178
+ }
179
+ };
180
+ process();
181
+ return { abort: () => controller.abort() };
182
+ }
183
+ // ===== Conversations =====
184
+ async getConversations(walletAddress) {
185
+ const res = await fetch(
186
+ `${this.baseUrl}/conversations?walletAddress=${encodeURIComponent(walletAddress)}`,
187
+ { headers: this.headers() }
188
+ );
189
+ if (!res.ok) return [];
190
+ const data = await res.json();
191
+ return data.conversations || [];
192
+ }
193
+ async getMessages(conversationId) {
194
+ const res = await fetch(
195
+ `${this.baseUrl}/conversations/${conversationId}/messages`,
196
+ { headers: this.headers() }
197
+ );
198
+ if (!res.ok) return [];
199
+ const data = await res.json();
200
+ return data.messages || [];
201
+ }
202
+ async renameConversation(id, title, walletAddress) {
203
+ await fetch(`${this.baseUrl}/conversations/${id}`, {
204
+ method: "PATCH",
205
+ headers: this.headers(true),
206
+ body: JSON.stringify({ title, walletAddress })
207
+ });
208
+ }
209
+ async deleteConversation(id, walletAddress) {
210
+ await fetch(
211
+ `${this.baseUrl}/conversations/${id}?walletAddress=${encodeURIComponent(walletAddress)}`,
212
+ { method: "DELETE", headers: this.headers() }
213
+ );
214
+ }
215
+ // ===== Tools =====
216
+ async listTools() {
217
+ const res = await fetch(`${this.baseUrl}/tools/list`, {
218
+ headers: this.headers()
219
+ });
220
+ if (!res.ok) return [];
221
+ const data = await res.json();
222
+ return data.tools || [];
223
+ }
224
+ async callTool(name, params) {
225
+ const res = await fetch(`${this.baseUrl}/tools/call`, {
226
+ method: "POST",
227
+ headers: this.headers(true),
228
+ body: JSON.stringify({ tool: name, params })
229
+ });
230
+ return res.json();
231
+ }
232
+ };
233
+ export {
234
+ ChainAIClient,
235
+ dispatchSSEEvent,
236
+ parseSSEStream
237
+ };
238
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/stream.ts","../src/client.ts"],"sourcesContent":["import type {\n SSEEventType,\n StreamCallbacks,\n UnsignedTransaction,\n ChartData,\n HyperliquidSignRequest,\n HyperliquidDepositRequest,\n OnrampRequest,\n} from \"./types.js\";\n\nexport interface SSEEvent {\n event: SSEEventType;\n data: string;\n}\n\n/**\n * Parses an SSE response body into a stream of typed events.\n * Uses the same buffer-splitting approach as the frontend's streamChat.\n */\nexport async function* parseSSEStream(\n body: ReadableStream<Uint8Array>\n): AsyncGenerator<SSEEvent> {\n const reader = body.getReader();\n const decoder = new TextDecoder();\n let buffer = \"\";\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const parts = buffer.split(\"\\n\\n\");\n buffer = parts.pop() || \"\";\n\n for (const part of parts) {\n const lines = part.split(\"\\n\");\n let eventType = \"\";\n const dataLines: string[] = [];\n\n for (const line of lines) {\n if (line.startsWith(\"event: \")) {\n eventType = line.slice(7).trim();\n } else if (line.startsWith(\"data: \")) {\n dataLines.push(line.slice(6));\n }\n }\n\n if (eventType && dataLines.length > 0) {\n yield {\n event: eventType as SSEEventType,\n data: dataLines.join(\"\\n\"),\n };\n }\n }\n }\n } finally {\n reader.releaseLock();\n }\n}\n\n/**\n * Dispatches SSE events to the appropriate callbacks.\n */\nexport function dispatchSSEEvent(\n event: SSEEvent,\n callbacks: StreamCallbacks\n): void {\n const { event: eventType, data } = event;\n\n switch (eventType) {\n case \"text\":\n callbacks.onText?.(data);\n break;\n case \"tool_call\":\n try {\n const parsed = JSON.parse(data);\n callbacks.onToolCall?.(parsed.name, parsed.input || {});\n } catch {\n /* ignore */\n }\n break;\n case \"tool_done\":\n try {\n const parsed = JSON.parse(data);\n callbacks.onToolDone?.(parsed.name, parsed.success ?? true);\n } catch {\n /* ignore */\n }\n break;\n case \"transaction\":\n try {\n callbacks.onTransaction?.(JSON.parse(data) as UnsignedTransaction);\n } catch {\n /* ignore */\n }\n break;\n case \"chart\":\n try {\n callbacks.onChart?.(JSON.parse(data) as ChartData);\n } catch {\n /* ignore */\n }\n break;\n case \"sign_typed_data\":\n try {\n callbacks.onSignRequest?.(\n JSON.parse(data) as HyperliquidSignRequest\n );\n } catch {\n /* ignore */\n }\n break;\n case \"hl_deposit\":\n try {\n callbacks.onDepositRequest?.(\n JSON.parse(data) as HyperliquidDepositRequest\n );\n } catch {\n /* ignore */\n }\n break;\n case \"moonpay_onramp\":\n try {\n callbacks.onOnrampRequest?.(JSON.parse(data) as OnrampRequest);\n } catch {\n /* ignore */\n }\n break;\n case \"error\":\n callbacks.onError?.(data);\n break;\n case \"done\":\n try {\n callbacks.onDone?.(JSON.parse(data));\n } catch {\n callbacks.onDone?.({ conversationId: \"\" });\n }\n break;\n }\n}\n","import type {\n ClientConfig,\n ChatOptions,\n ChatResponse,\n ConversationSummary,\n ConversationMessage,\n ToolDefinitionInfo,\n ToolResult,\n StreamCallbacks,\n} from \"./types.js\";\nimport { parseSSEStream, dispatchSSEEvent } from \"./stream.js\";\n\nconst DEFAULT_BASE_URL = \"http://localhost:3000\";\n\nexport class ChainAIClient {\n private apiKey: string;\n private baseUrl: string;\n\n constructor(config: ClientConfig) {\n if (!config.apiKey) {\n throw new Error(\"ChainAIClient requires an apiKey\");\n }\n this.apiKey = config.apiKey;\n this.baseUrl = (config.baseUrl || DEFAULT_BASE_URL).replace(/\\/+$/, \"\");\n }\n\n private headers(json = false): Record<string, string> {\n const h: Record<string, string> = {\n \"X-API-Key\": this.apiKey,\n };\n if (json) h[\"Content-Type\"] = \"application/json\";\n return h;\n }\n\n // ===== Non-streaming Chat =====\n async chat(message: string, options?: ChatOptions): Promise<ChatResponse> {\n const res = await fetch(`${this.baseUrl}/chat`, {\n method: \"POST\",\n headers: this.headers(true),\n body: JSON.stringify({\n message,\n conversationId: options?.conversationId,\n walletContext: options?.walletContext,\n walletAddress: options?.walletAddress,\n }),\n });\n if (!res.ok) {\n const err = await res.json().catch(() => ({ error: res.statusText }));\n throw new Error(\n (err as { error?: string }).error || `API error: ${res.status}`\n );\n }\n return res.json();\n }\n\n // ===== Streaming Chat =====\n async chatStream(\n message: string,\n options?: ChatOptions,\n callbacks?: StreamCallbacks\n ): Promise<{ abort: () => void }> {\n const controller = new AbortController();\n\n const res = await fetch(`${this.baseUrl}/chat/stream`, {\n method: \"POST\",\n headers: this.headers(true),\n body: JSON.stringify({\n message,\n conversationId: options?.conversationId,\n walletContext: options?.walletContext,\n walletAddress: options?.walletAddress,\n }),\n signal: controller.signal,\n });\n\n if (!res.ok) {\n const err = await res.json().catch(() => ({ error: res.statusText }));\n throw new Error(\n (err as { error?: string }).error || `API error: ${res.status}`\n );\n }\n\n if (!res.body) {\n throw new Error(\"No response body\");\n }\n\n // Process stream in background (non-blocking)\n const process = async () => {\n try {\n for await (const event of parseSSEStream(res.body!)) {\n if (callbacks) {\n dispatchSSEEvent(event, callbacks);\n }\n }\n } catch (err) {\n if ((err as Error).name !== \"AbortError\") {\n callbacks?.onError?.(\n err instanceof Error ? err.message : String(err)\n );\n }\n }\n };\n\n process();\n\n return { abort: () => controller.abort() };\n }\n\n // ===== Conversations =====\n async getConversations(\n walletAddress: string\n ): Promise<ConversationSummary[]> {\n const res = await fetch(\n `${this.baseUrl}/conversations?walletAddress=${encodeURIComponent(walletAddress)}`,\n { headers: this.headers() }\n );\n if (!res.ok) return [];\n const data = (await res.json()) as {\n conversations?: ConversationSummary[];\n };\n return data.conversations || [];\n }\n\n async getMessages(conversationId: string): Promise<ConversationMessage[]> {\n const res = await fetch(\n `${this.baseUrl}/conversations/${conversationId}/messages`,\n { headers: this.headers() }\n );\n if (!res.ok) return [];\n const data = (await res.json()) as {\n messages?: ConversationMessage[];\n };\n return data.messages || [];\n }\n\n async renameConversation(\n id: string,\n title: string,\n walletAddress: string\n ): Promise<void> {\n await fetch(`${this.baseUrl}/conversations/${id}`, {\n method: \"PATCH\",\n headers: this.headers(true),\n body: JSON.stringify({ title, walletAddress }),\n });\n }\n\n async deleteConversation(\n id: string,\n walletAddress: string\n ): Promise<void> {\n await fetch(\n `${this.baseUrl}/conversations/${id}?walletAddress=${encodeURIComponent(walletAddress)}`,\n { method: \"DELETE\", headers: this.headers() }\n );\n }\n\n // ===== Tools =====\n async listTools(): Promise<ToolDefinitionInfo[]> {\n const res = await fetch(`${this.baseUrl}/tools/list`, {\n headers: this.headers(),\n });\n if (!res.ok) return [];\n const data = (await res.json()) as { tools?: ToolDefinitionInfo[] };\n return data.tools || [];\n }\n\n async callTool(\n name: string,\n params: Record<string, unknown>\n ): Promise<ToolResult> {\n const res = await fetch(`${this.baseUrl}/tools/call`, {\n method: \"POST\",\n headers: this.headers(true),\n body: JSON.stringify({ tool: name, params }),\n });\n return res.json();\n }\n}\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,41 +1,29 @@
1
1
  {
2
2
  "name": "@chainai/core",
3
- "version": "1.0.4",
4
- "description": "Core client library for Chain AI - Natural language blockchain assistant",
5
- "main": "dist/index.js",
3
+ "version": "1.1.0",
4
+ "description": "Pure TypeScript client for ChainAI blockchain assistant API",
5
+ "type": "module",
6
+ "main": "dist/index.cjs",
7
+ "module": "dist/index.js",
6
8
  "types": "dist/index.d.ts",
7
- "files": [
8
- "dist"
9
- ],
10
- "scripts": {
11
- "build": "tsc",
12
- "dev": "tsc --watch",
13
- "test": "jest",
14
- "lint": "eslint src --ext .ts",
15
- "type-check": "tsc --noEmit"
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js",
13
+ "require": "./dist/index.cjs"
14
+ }
16
15
  },
17
- "keywords": [
18
- "blockchain",
19
- "ai",
20
- "nlp",
21
- "crypto",
22
- "icp",
23
- "internet-computer",
24
- "chain-ai"
25
- ],
26
- "author": "Chain AI",
27
- "license": "MIT",
28
- "dependencies": {
29
- "@dfinity/agent": "^3.4.3",
30
- "@dfinity/candid": "^3.4.3",
31
- "@dfinity/principal": "^3.4.3"
16
+ "files": ["dist"],
17
+ "scripts": {
18
+ "build": "tsup",
19
+ "dev": "tsup --watch",
20
+ "clean": "rm -rf dist",
21
+ "typecheck": "tsc --noEmit"
32
22
  },
33
23
  "devDependencies": {
34
- "@types/node": "^20.11.0",
35
- "typescript": "^5.4.5"
24
+ "tsup": "^8.0.0",
25
+ "typescript": "^5.9.3"
36
26
  },
37
- "repository": {
38
- "type": "git",
39
- "url": "https://github.com/chain-ai/npm-packages.git"
40
- }
27
+ "keywords": ["chainai", "blockchain", "ai", "sdk"],
28
+ "license": "MIT"
41
29
  }
package/README.md DELETED
@@ -1,162 +0,0 @@
1
- # @chainai/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 @chainai/core
9
- ```
10
-
11
- ## Quick Start
12
-
13
- ```typescript
14
- import { ChainAIClient } from '@chainai/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 DELETED
@@ -1,57 +0,0 @@
1
- /**
2
- * ChainAIClient - Main client class for interacting with Chain AI
3
- */
4
- import type { ChainAIConfig, ChatRequest, ChatResponse, StreamCallbacks, ValidationResult, ResponseCustomization, WalletProvider } from './types';
5
- export declare class ChainAIClient {
6
- private icService;
7
- private nlpService;
8
- private apiKey;
9
- private config;
10
- private walletProvider?;
11
- constructor(config: ChainAIConfig);
12
- /**
13
- * Set or update the wallet provider
14
- */
15
- setWalletProvider(provider: WalletProvider): void;
16
- /**
17
- * Get current wallet context from the provider
18
- */
19
- private getWalletContext;
20
- /**
21
- * Validate the API key
22
- */
23
- validateApiKey(): Promise<ValidationResult>;
24
- /**
25
- * Send a chat message and get AI response
26
- * Automatically includes wallet context if a walletProvider is configured
27
- */
28
- chat(request: Omit<ChatRequest, 'apiKey'>): Promise<ChatResponse>;
29
- /**
30
- * Stream chat response with real-time updates
31
- * Automatically includes wallet context if a walletProvider is configured
32
- */
33
- streamChat(request: Omit<ChatRequest, 'apiKey'>, callbacks: StreamCallbacks): Promise<void>;
34
- /**
35
- * Get current response customization settings
36
- */
37
- getCustomization(): Promise<ResponseCustomization | null>;
38
- /**
39
- * Update response customization settings
40
- */
41
- updateCustomization(customization: Partial<ResponseCustomization>): Promise<{
42
- ok: boolean;
43
- message?: string;
44
- error?: string;
45
- }>;
46
- /**
47
- * Reset customization to defaults
48
- */
49
- resetCustomization(): Promise<{
50
- ok: boolean;
51
- message?: string;
52
- }>;
53
- /**
54
- * Check canister health
55
- */
56
- health(): Promise<string>;
57
- }
package/dist/client.js DELETED
@@ -1,104 +0,0 @@
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
- this.walletProvider = config.walletProvider;
14
- // Initialize IC service
15
- this.icService = new ic_service_1.ICService({
16
- host: config.host || 'https://icp0.io',
17
- nlpEdgeCanisterId: config.nlpEdgeCanisterId || 'ypzdi-iqaaa-aaaam-qfhla-cai',
18
- developerManagerCanisterId: config.developerManagerCanisterId || 'yiyf4-fiaaa-aaaam-qfhlq-cai',
19
- });
20
- // Initialize NLP service
21
- this.nlpService = new nlp_service_1.NLPService(this.icService);
22
- }
23
- /**
24
- * Set or update the wallet provider
25
- */
26
- setWalletProvider(provider) {
27
- this.walletProvider = provider;
28
- }
29
- /**
30
- * Get current wallet context from the provider
31
- */
32
- async getWalletContext() {
33
- if (!this.walletProvider) {
34
- return undefined;
35
- }
36
- try {
37
- const context = await this.walletProvider();
38
- return context;
39
- }
40
- catch (error) {
41
- console.warn('Failed to get wallet context:', error);
42
- return undefined;
43
- }
44
- }
45
- /**
46
- * Validate the API key
47
- */
48
- async validateApiKey() {
49
- return this.icService.validateApiKey(this.apiKey);
50
- }
51
- /**
52
- * Send a chat message and get AI response
53
- * Automatically includes wallet context if a walletProvider is configured
54
- */
55
- async chat(request) {
56
- // Get wallet context from provider if available
57
- const walletContext = request.walletContext || await this.getWalletContext();
58
- const fullRequest = {
59
- ...request,
60
- apiKey: this.apiKey,
61
- walletContext,
62
- };
63
- return this.nlpService.chat(fullRequest);
64
- }
65
- /**
66
- * Stream chat response with real-time updates
67
- * Automatically includes wallet context if a walletProvider is configured
68
- */
69
- async streamChat(request, callbacks) {
70
- // Get wallet context from provider if available
71
- const walletContext = request.walletContext || await this.getWalletContext();
72
- const fullRequest = {
73
- ...request,
74
- apiKey: this.apiKey,
75
- walletContext,
76
- };
77
- return this.nlpService.streamChat(fullRequest, callbacks);
78
- }
79
- /**
80
- * Get current response customization settings
81
- */
82
- async getCustomization() {
83
- return this.icService.getResponseCustomization(this.apiKey);
84
- }
85
- /**
86
- * Update response customization settings
87
- */
88
- async updateCustomization(customization) {
89
- return this.icService.setResponseCustomization(this.apiKey, customization);
90
- }
91
- /**
92
- * Reset customization to defaults
93
- */
94
- async resetCustomization() {
95
- return this.icService.deleteResponseCustomization(this.apiKey);
96
- }
97
- /**
98
- * Check canister health
99
- */
100
- async health() {
101
- return this.nlpService.health();
102
- }
103
- }
104
- exports.ChainAIClient = ChainAIClient;