@amaster.ai/client 1.0.0-alpha.1
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/LICENSE +21 -0
- package/README.md +847 -0
- package/dist/index.cjs +162 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +421 -0
- package/dist/index.d.ts +421 -0
- package/dist/index.js +160 -0
- package/dist/index.js.map +1 -0
- package/package.json +108 -0
- package/types/__tests__/type-checks.test-d.ts +163 -0
- package/types/asr.d.ts +237 -0
- package/types/auth/code-auth.d.ts +105 -0
- package/types/auth/index.d.ts +138 -0
- package/types/auth/oauth.d.ts +143 -0
- package/types/auth/password-auth.d.ts +226 -0
- package/types/auth/profile.d.ts +64 -0
- package/types/auth/user.d.ts +73 -0
- package/types/bpm.d.ts +621 -0
- package/types/common.d.ts +140 -0
- package/types/copilot.d.ts +49 -0
- package/types/entity.d.ts +433 -0
- package/types/function.d.ts +41 -0
- package/types/http.d.ts +95 -0
- package/types/index.d.ts +338 -0
- package/types/s3.d.ts +96 -0
- package/types/tts.d.ts +88 -0
- package/types/workflow.d.ts +142 -0
package/README.md
ADDED
|
@@ -0,0 +1,847 @@
|
|
|
1
|
+
# @amaster.ai/client
|
|
2
|
+
|
|
3
|
+
> Unified API client for the Amaster platform - All services in one package
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/@amaster.ai/client)
|
|
6
|
+
[](https://opensource.org/licenses/MIT)
|
|
7
|
+
|
|
8
|
+
## 🤖 AI-Friendly Documentation
|
|
9
|
+
|
|
10
|
+
This package is designed with AI tools (GitHub Copilot, Cursor, etc.) in mind:
|
|
11
|
+
|
|
12
|
+
- **Modular Type Definitions**: API documentation split into focused modules
|
|
13
|
+
- **Rich JSDoc**: Every method includes detailed descriptions and examples
|
|
14
|
+
- **On-Demand Loading**: AI tools only load relevant type files when needed
|
|
15
|
+
- **Type-Driven Learning**: Full TypeScript support helps AI understand API patterns
|
|
16
|
+
|
|
17
|
+
### Type Documentation Structure
|
|
18
|
+
|
|
19
|
+
```
|
|
20
|
+
types/
|
|
21
|
+
├── index.d.ts # Main entry (lightweight)
|
|
22
|
+
├── auth/ # Authentication (split into 7 focused modules)
|
|
23
|
+
│ ├── user.d.ts
|
|
24
|
+
│ ├── password-auth.d.ts
|
|
25
|
+
│ ├── code-auth.d.ts
|
|
26
|
+
│ ├── oauth.d.ts
|
|
27
|
+
│ ├── permissions.d.ts
|
|
28
|
+
│ ├── profile.d.ts
|
|
29
|
+
│ └── index.d.ts
|
|
30
|
+
├── entity.d.ts # Entity CRUD operations
|
|
31
|
+
├── bpm.d.ts # Business Process Management
|
|
32
|
+
├── workflow.d.ts # Workflow execution
|
|
33
|
+
├── asr.d.ts # Speech Recognition (WebSocket)
|
|
34
|
+
├── copilot.d.ts # AI Assistant / Chat
|
|
35
|
+
├── function.d.ts # Function invocation
|
|
36
|
+
└── tts.d.ts # Text-to-Speech (WebSocket)
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Each module contains:
|
|
40
|
+
|
|
41
|
+
- Complete method signatures
|
|
42
|
+
- Parameter descriptions
|
|
43
|
+
- Return type definitions
|
|
44
|
+
- Multiple usage examples
|
|
45
|
+
- Best practices
|
|
46
|
+
|
|
47
|
+
## 🚀 Overview
|
|
48
|
+
|
|
49
|
+
`@amaster.ai/client` is a unified JavaScript/TypeScript client that provides a simple, consistent interface to all Amaster platform services. Inspired by Supabase's elegant API design, it offers:
|
|
50
|
+
|
|
51
|
+
✨ **Single client instance** for all services
|
|
52
|
+
🔐 **Automatic authentication** - tokens attached to all requests
|
|
53
|
+
🔄 **Token auto-refresh** - never worry about expiration
|
|
54
|
+
📦 **Type-safe** - Full TypeScript support with auto-completion
|
|
55
|
+
🎯 **Simple API** - Clean, consistent method naming
|
|
56
|
+
🌐 **Complete Integration** - Auth, Entity, BPM, Workflow, ASR, Copilot, Function, TTS, S3
|
|
57
|
+
|
|
58
|
+
## 📦 Installation
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
# npm
|
|
62
|
+
npm install @amaster.ai/client axios
|
|
63
|
+
|
|
64
|
+
# pnpm
|
|
65
|
+
pnpm add @amaster.ai/client axios
|
|
66
|
+
|
|
67
|
+
# yarn
|
|
68
|
+
yarn add @amaster.ai/client axios
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## 🎯 Quick Start
|
|
72
|
+
|
|
73
|
+
```typescript
|
|
74
|
+
import { createClient } from "@amaster.ai/client";
|
|
75
|
+
|
|
76
|
+
// 1. Create client instance (baseURL is optional)
|
|
77
|
+
const client = createClient({
|
|
78
|
+
baseURL: "https://api.amaster.ai", // Optional - auto-detects from env in Taro/Mini-program
|
|
79
|
+
onUnauthorized: () => {
|
|
80
|
+
// Handle unauthorized (redirect to login, show modal, etc.)
|
|
81
|
+
window.location.href = "/login";
|
|
82
|
+
},
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
// Or simply:
|
|
86
|
+
// const client = createClient({}); // Auto-uses VITE_API_BASE_URL or dev proxy
|
|
87
|
+
|
|
88
|
+
// 2. Login
|
|
89
|
+
await client.auth.login({
|
|
90
|
+
email: "user@example.com",
|
|
91
|
+
password: "password123",
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
// 3. Use any service - auth token is automatically attached!
|
|
95
|
+
const users = await client.entity.list("default", "users");
|
|
96
|
+
const tasks = await client.bpm.getMyTasks();
|
|
97
|
+
const result = await client.workflow.execute("my-workflow", { input: {} });
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## 🔑 Authentication
|
|
101
|
+
|
|
102
|
+
### Login
|
|
103
|
+
|
|
104
|
+
```typescript
|
|
105
|
+
// Email/Password login
|
|
106
|
+
const result = await client.auth.login({
|
|
107
|
+
email: "user@example.com",
|
|
108
|
+
password: "password123",
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
if (result.success) {
|
|
112
|
+
console.log("Logged in:", result.data.user);
|
|
113
|
+
}
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### Register
|
|
117
|
+
|
|
118
|
+
```typescript
|
|
119
|
+
const result = await client.auth.register({
|
|
120
|
+
username: "johndoe",
|
|
121
|
+
email: "john@example.com",
|
|
122
|
+
password: "securePassword123",
|
|
123
|
+
});
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### Get Current User
|
|
127
|
+
|
|
128
|
+
```typescript
|
|
129
|
+
const result = await client.auth.getMe();
|
|
130
|
+
if (result.success) {
|
|
131
|
+
console.log("Current user:", result.data);
|
|
132
|
+
}
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### Logout
|
|
136
|
+
|
|
137
|
+
```typescript
|
|
138
|
+
await client.auth.logout();
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### Check Authentication Status
|
|
142
|
+
|
|
143
|
+
```typescript
|
|
144
|
+
if (client.isAuthenticated()) {
|
|
145
|
+
console.log("User is logged in");
|
|
146
|
+
}
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
## 📊 Entity Operations (CRUD)
|
|
150
|
+
|
|
151
|
+
Full CRUD operations for your data entities with type safety.
|
|
152
|
+
|
|
153
|
+
### List Entities
|
|
154
|
+
|
|
155
|
+
```typescript
|
|
156
|
+
const result = await client.entity.list("default", "users", {
|
|
157
|
+
page: 1,
|
|
158
|
+
perPage: 20,
|
|
159
|
+
orderBy: "createdAt",
|
|
160
|
+
orderDir: "desc",
|
|
161
|
+
// Filters
|
|
162
|
+
"status[eq]": "active",
|
|
163
|
+
"age[gt]": 18,
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
if (result.success) {
|
|
167
|
+
const { items, total, page, perPage } = result.data;
|
|
168
|
+
console.log(`Found ${total} users`);
|
|
169
|
+
}
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### Get Single Entity
|
|
173
|
+
|
|
174
|
+
```typescript
|
|
175
|
+
const result = await client.entity.get("default", "users", 123);
|
|
176
|
+
if (result.success) {
|
|
177
|
+
console.log("User:", result.data);
|
|
178
|
+
}
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
### Create Entity
|
|
182
|
+
|
|
183
|
+
```typescript
|
|
184
|
+
const result = await client.entity.create("default", "users", {
|
|
185
|
+
name: "John Doe",
|
|
186
|
+
email: "john@example.com",
|
|
187
|
+
status: "active",
|
|
188
|
+
});
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### Update Entity
|
|
192
|
+
|
|
193
|
+
```typescript
|
|
194
|
+
const result = await client.entity.update("default", "users", 123, {
|
|
195
|
+
name: "Jane Doe",
|
|
196
|
+
status: "inactive",
|
|
197
|
+
});
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
### Delete Entity
|
|
201
|
+
|
|
202
|
+
```typescript
|
|
203
|
+
await client.entity.delete("default", "users", 123);
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
### Bulk Operations
|
|
207
|
+
|
|
208
|
+
```typescript
|
|
209
|
+
// Bulk update
|
|
210
|
+
await client.entity.bulkUpdate("default", "users", [
|
|
211
|
+
{ id: 1, status: "active" },
|
|
212
|
+
{ id: 2, status: "inactive" },
|
|
213
|
+
]);
|
|
214
|
+
|
|
215
|
+
// Bulk delete
|
|
216
|
+
await client.entity.bulkDelete("default", "users", [1, 2, 3]);
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
## 🔄 BPM (Business Process Management)
|
|
220
|
+
|
|
221
|
+
Manage business processes powered by Camunda 7.
|
|
222
|
+
|
|
223
|
+
### Start a Process
|
|
224
|
+
|
|
225
|
+
```typescript
|
|
226
|
+
const result = await client.bpm.startProcess({
|
|
227
|
+
processKey: "approval-process",
|
|
228
|
+
businessKey: "ORDER-12345",
|
|
229
|
+
variables: {
|
|
230
|
+
amount: 1000,
|
|
231
|
+
requester: "john@example.com",
|
|
232
|
+
},
|
|
233
|
+
});
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
### Get My Tasks
|
|
237
|
+
|
|
238
|
+
```typescript
|
|
239
|
+
const result = await client.bpm.getMyTasks({
|
|
240
|
+
page: 1,
|
|
241
|
+
perPage: 20,
|
|
242
|
+
sortBy: "created",
|
|
243
|
+
sortOrder: "desc",
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
if (result.success) {
|
|
247
|
+
console.log("Tasks:", result.data.items);
|
|
248
|
+
}
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
### Complete a Task
|
|
252
|
+
|
|
253
|
+
```typescript
|
|
254
|
+
await client.bpm.completeTask("task-id", {
|
|
255
|
+
approved: true,
|
|
256
|
+
comments: "Looks good!",
|
|
257
|
+
});
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
### Claim a Task
|
|
261
|
+
|
|
262
|
+
```typescript
|
|
263
|
+
await client.bpm.claimTask("task-id");
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
## ⚡ Workflow Execution
|
|
267
|
+
|
|
268
|
+
Execute workflows and automation flows.
|
|
269
|
+
|
|
270
|
+
```typescript
|
|
271
|
+
const result = await client.workflow.execute("data-processing-workflow", {
|
|
272
|
+
input: {
|
|
273
|
+
dataSource: "users",
|
|
274
|
+
filters: { status: "active" },
|
|
275
|
+
},
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
if (result.success) {
|
|
279
|
+
console.log("Workflow result:", result.data);
|
|
280
|
+
}
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
## 🎙️ ASR (Automatic Speech Recognition)
|
|
284
|
+
|
|
285
|
+
实时语音识别支持 WebSocket 流式识别和 HTTP 按压识别两种方式。
|
|
286
|
+
|
|
287
|
+
### WebSocket ASR(实时流式识别)
|
|
288
|
+
|
|
289
|
+
适合需要实时看到识别结果的场景,如语音输入、实时字幕等。
|
|
290
|
+
|
|
291
|
+
```tsx
|
|
292
|
+
import { useRef, useState } from "react";
|
|
293
|
+
import type { ASRClient } from "@amaster.ai/client";
|
|
294
|
+
|
|
295
|
+
function ASRRealtimeDemo() {
|
|
296
|
+
const asrRef = useRef<ASRClient | null>(null);
|
|
297
|
+
const [result, setResult] = useState("");
|
|
298
|
+
const [status, setStatus] = useState("idle"); // idle | connecting | ready | error | closed
|
|
299
|
+
|
|
300
|
+
const start = async () => {
|
|
301
|
+
let finalResult = "";
|
|
302
|
+
let temp = "";
|
|
303
|
+
|
|
304
|
+
setStatus("connecting");
|
|
305
|
+
|
|
306
|
+
const asrClient = client.asr({
|
|
307
|
+
onReady() {
|
|
308
|
+
setStatus("ready");
|
|
309
|
+
},
|
|
310
|
+
onTranscript(text, isFinal) {
|
|
311
|
+
if (!isFinal) {
|
|
312
|
+
temp = text;
|
|
313
|
+
setResult(finalResult + temp);
|
|
314
|
+
} else {
|
|
315
|
+
temp = "";
|
|
316
|
+
finalResult += text;
|
|
317
|
+
setResult(finalResult);
|
|
318
|
+
}
|
|
319
|
+
},
|
|
320
|
+
onError(err) {
|
|
321
|
+
console.error(err);
|
|
322
|
+
setStatus("error");
|
|
323
|
+
},
|
|
324
|
+
onClose() {
|
|
325
|
+
setStatus("closed");
|
|
326
|
+
},
|
|
327
|
+
});
|
|
328
|
+
|
|
329
|
+
await asrClient.connect();
|
|
330
|
+
await asrClient.startRecording();
|
|
331
|
+
asrRef.current = asrClient;
|
|
332
|
+
};
|
|
333
|
+
|
|
334
|
+
const stop = () => {
|
|
335
|
+
asrRef.current?.stopRecording();
|
|
336
|
+
asrRef.current?.close();
|
|
337
|
+
asrRef.current = null;
|
|
338
|
+
setStatus("idle");
|
|
339
|
+
};
|
|
340
|
+
|
|
341
|
+
return (
|
|
342
|
+
<div>
|
|
343
|
+
<div>状态: {status}</div>
|
|
344
|
+
<button onClick={start} disabled={status === "connecting" || status === "ready"}>
|
|
345
|
+
开始录音
|
|
346
|
+
</button>
|
|
347
|
+
<button onClick={stop} disabled={status !== "ready"}>
|
|
348
|
+
停止
|
|
349
|
+
</button>
|
|
350
|
+
<div>识别结果: {result || "(等待说话...)"}</div>
|
|
351
|
+
</div>
|
|
352
|
+
);
|
|
353
|
+
}
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
### HTTP ASR(按压识别)
|
|
357
|
+
|
|
358
|
+
适合按住说话、松开识别的场景,如语音消息、语音搜索等。
|
|
359
|
+
|
|
360
|
+
```tsx
|
|
361
|
+
import { useRef, useState } from "react";
|
|
362
|
+
import type { ASRHttpClient } from "@amaster.ai/client";
|
|
363
|
+
|
|
364
|
+
function ASRPressToTalkDemo() {
|
|
365
|
+
const clientRef = useRef<ASRHttpClient | null>(null);
|
|
366
|
+
const [recording, setRecording] = useState(false);
|
|
367
|
+
const [text, setText] = useState("");
|
|
368
|
+
const [error, setError] = useState<string | null>(null);
|
|
369
|
+
|
|
370
|
+
if (!clientRef.current) {
|
|
371
|
+
clientRef.current = client.asrHttp({
|
|
372
|
+
onRecordingStart() {
|
|
373
|
+
setRecording(true);
|
|
374
|
+
setText("");
|
|
375
|
+
setError(null);
|
|
376
|
+
},
|
|
377
|
+
onRecordingStop() {
|
|
378
|
+
setRecording(false);
|
|
379
|
+
},
|
|
380
|
+
onResult(result) {
|
|
381
|
+
setText(result);
|
|
382
|
+
},
|
|
383
|
+
onError(err) {
|
|
384
|
+
setError(err.message);
|
|
385
|
+
},
|
|
386
|
+
});
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
const asrHttpClient = clientRef.current;
|
|
390
|
+
|
|
391
|
+
return (
|
|
392
|
+
<div>
|
|
393
|
+
<button
|
|
394
|
+
onMouseDown={() => asrHttpClient.startRecording()}
|
|
395
|
+
onMouseUp={() => asrHttpClient.stopRecording()}
|
|
396
|
+
onTouchStart={() => asrHttpClient.startRecording()}
|
|
397
|
+
onTouchEnd={() => asrHttpClient.stopRecording()}
|
|
398
|
+
style={{
|
|
399
|
+
padding: "12px 24px",
|
|
400
|
+
background: recording ? "#f87171" : "#4ade80",
|
|
401
|
+
}}
|
|
402
|
+
>
|
|
403
|
+
{recording ? "松开识别" : "按住说话"}
|
|
404
|
+
</button>
|
|
405
|
+
|
|
406
|
+
<div>
|
|
407
|
+
<strong>识别结果:</strong>
|
|
408
|
+
<div>{text || "(暂无)"}</div>
|
|
409
|
+
</div>
|
|
410
|
+
|
|
411
|
+
{error && <div style={{ color: "red" }}>错误:{error}</div>}
|
|
412
|
+
</div>
|
|
413
|
+
);
|
|
414
|
+
}
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
**ASR Client 配置说明:**
|
|
418
|
+
|
|
419
|
+
| 参数 | 类型 | 说明 |
|
|
420
|
+
| ------------------ | ------------------------------------------ | ------------------------------ |
|
|
421
|
+
| `onReady` | `() => void` | 会话创建完成 |
|
|
422
|
+
| `onSpeechStart` | `() => void` | 检测到语音开始(仅 WebSocket) |
|
|
423
|
+
| `onSpeechEnd` | `() => void` | 检测到语音结束(仅 WebSocket) |
|
|
424
|
+
| `onTranscript` | `(text: string, isFinal: boolean) => void` | 转写回调(WebSocket) |
|
|
425
|
+
| `onRecordingStart` | `() => void` | 录音开始回调(仅 HTTP) |
|
|
426
|
+
| `onRecordingStop` | `() => void` | 录音停止回调(仅 HTTP) |
|
|
427
|
+
| `onResult` | `(text: string) => void` | 识别结果回调(HTTP) |
|
|
428
|
+
| `onError` | `(error: Error) => void` | 错误回调 |
|
|
429
|
+
| `onClose` | `() => void` | 连接关闭回调(WebSocket) |
|
|
430
|
+
|
|
431
|
+
## 🔊 TTS (Text-to-Speech)
|
|
432
|
+
|
|
433
|
+
WebSocket 实时语音合成。
|
|
434
|
+
|
|
435
|
+
```tsx
|
|
436
|
+
import { useRef, useState } from "react";
|
|
437
|
+
import type { TTSClient } from "@amaster.ai/client";
|
|
438
|
+
|
|
439
|
+
function TTSDemo() {
|
|
440
|
+
const [voice, setVoice] = useState("Cherry");
|
|
441
|
+
const [connected, setConnected] = useState(false);
|
|
442
|
+
const [status, setStatus] = useState("disconnected");
|
|
443
|
+
const [text, setText] = useState("你好,欢迎使用实时语音合成服务。");
|
|
444
|
+
const clientRef = useRef<TTSClient | null>(null);
|
|
445
|
+
|
|
446
|
+
const connectTTS = () => {
|
|
447
|
+
if (clientRef.current) return;
|
|
448
|
+
|
|
449
|
+
const ttsClient = client.tts({
|
|
450
|
+
voice,
|
|
451
|
+
autoPlay: true,
|
|
452
|
+
audioFormat: "pcm",
|
|
453
|
+
sampleRate: 24000,
|
|
454
|
+
onReady: () => {
|
|
455
|
+
setConnected(true);
|
|
456
|
+
setStatus("connected");
|
|
457
|
+
},
|
|
458
|
+
onAudioStart: () => setStatus("playing"),
|
|
459
|
+
onAudioEnd: () => setStatus("connected"),
|
|
460
|
+
onAudioChunk: (chunks) => {
|
|
461
|
+
console.log("收到音频片段:", chunks.length);
|
|
462
|
+
},
|
|
463
|
+
onError: (err) => {
|
|
464
|
+
console.error("TTS Error:", err);
|
|
465
|
+
setStatus("error");
|
|
466
|
+
},
|
|
467
|
+
});
|
|
468
|
+
|
|
469
|
+
ttsClient.connect();
|
|
470
|
+
clientRef.current = ttsClient;
|
|
471
|
+
};
|
|
472
|
+
|
|
473
|
+
const sendTTS = () => {
|
|
474
|
+
if (!text || !clientRef.current) return;
|
|
475
|
+
clientRef.current.speak(text);
|
|
476
|
+
setStatus("sending");
|
|
477
|
+
};
|
|
478
|
+
|
|
479
|
+
const disconnectTTS = () => {
|
|
480
|
+
clientRef.current?.close();
|
|
481
|
+
clientRef.current = null;
|
|
482
|
+
setConnected(false);
|
|
483
|
+
setStatus("disconnected");
|
|
484
|
+
};
|
|
485
|
+
|
|
486
|
+
return (
|
|
487
|
+
<div>
|
|
488
|
+
<h3>🔊 实时语音合成</h3>
|
|
489
|
+
<div>状态: {status}</div>
|
|
490
|
+
|
|
491
|
+
<div>
|
|
492
|
+
<label>音色:</label>
|
|
493
|
+
<select value={voice} onChange={(e) => setVoice(e.target.value)}>
|
|
494
|
+
<option value="Cherry">Cherry - 甜美女声</option>
|
|
495
|
+
<option value="Serena">苏瑶 - 温柔小姐姐</option>
|
|
496
|
+
<option value="Ethan">晨煦 - 标准普通话</option>
|
|
497
|
+
<option value="Chelsie">千雪 - 二次元虚拟女友</option>
|
|
498
|
+
<option value="Peter">天津话</option>
|
|
499
|
+
</select>
|
|
500
|
+
</div>
|
|
501
|
+
|
|
502
|
+
<div>
|
|
503
|
+
<label>合成文本:</label>
|
|
504
|
+
<textarea rows={4} value={text} onChange={(e) => setText(e.target.value)} />
|
|
505
|
+
</div>
|
|
506
|
+
|
|
507
|
+
<div>
|
|
508
|
+
<button onClick={connectTTS} disabled={connected}>
|
|
509
|
+
连接
|
|
510
|
+
</button>
|
|
511
|
+
<button onClick={sendTTS} disabled={!connected}>
|
|
512
|
+
合成语音
|
|
513
|
+
</button>
|
|
514
|
+
<button onClick={disconnectTTS} disabled={!connected}>
|
|
515
|
+
断开
|
|
516
|
+
</button>
|
|
517
|
+
</div>
|
|
518
|
+
</div>
|
|
519
|
+
);
|
|
520
|
+
}
|
|
521
|
+
```
|
|
522
|
+
|
|
523
|
+
**TTS Client 配置说明:**
|
|
524
|
+
|
|
525
|
+
| 参数 | 类型 | 默认值 | 说明 |
|
|
526
|
+
| -------------- | ----------------------------------- | ---------- | ------------------------------ |
|
|
527
|
+
| `voice` | `string` | `"Cherry"` | 发音人名称 |
|
|
528
|
+
| `autoPlay` | `boolean` | `true` | 是否自动播放 |
|
|
529
|
+
| `audioFormat` | `"pcm" \| "mp3" \| "wav" \| "opus"` | `"pcm"` | 音频格式(内置播放仅支持 pcm) |
|
|
530
|
+
| `sampleRate` | `number` | `24000` | 采样率 |
|
|
531
|
+
| `onReady` | `() => void` | - | 会话就绪回调 |
|
|
532
|
+
| `onAudioStart` | `() => void` | - | 音频开始播放回调 |
|
|
533
|
+
| `onAudioEnd` | `() => void` | - | 音频播放结束回调 |
|
|
534
|
+
| `onAudioChunk` | `(chunks: string[]) => void` | - | 音频分片回调 |
|
|
535
|
+
| `onError` | `(error: Error) => void` | - | 错误回调 |
|
|
536
|
+
|
|
537
|
+
## 🤖 Copilot (AI Assistant)
|
|
538
|
+
|
|
539
|
+
AI assistant / chatbot API.
|
|
540
|
+
|
|
541
|
+
```typescript
|
|
542
|
+
// Simple chat
|
|
543
|
+
const result = await client.copilot.sendMessage([
|
|
544
|
+
{ role: "user", content: "Hello, how can you help?" },
|
|
545
|
+
]);
|
|
546
|
+
|
|
547
|
+
console.log(result.data.content);
|
|
548
|
+
|
|
549
|
+
// Streaming response
|
|
550
|
+
await client.copilot.sendMessage([{ role: "user", content: "Tell me a story" }], {
|
|
551
|
+
stream: true,
|
|
552
|
+
onChunk: (chunk) => console.log(chunk),
|
|
553
|
+
});
|
|
554
|
+
```
|
|
555
|
+
|
|
556
|
+
## ⚙️ Function Invocation
|
|
557
|
+
|
|
558
|
+
调用服务端函数。
|
|
559
|
+
|
|
560
|
+
```typescript
|
|
561
|
+
// Call a function
|
|
562
|
+
const result = await client.function.invoke<{ result: string }>("sendEmail", {
|
|
563
|
+
to: "user@example.com",
|
|
564
|
+
subject: "Hello",
|
|
565
|
+
});
|
|
566
|
+
|
|
567
|
+
if (result.data) {
|
|
568
|
+
console.log("Function result:", result.data.result);
|
|
569
|
+
}
|
|
570
|
+
```
|
|
571
|
+
|
|
572
|
+
## ☁️ S3 Storage
|
|
573
|
+
|
|
574
|
+
文件上传下载。
|
|
575
|
+
|
|
576
|
+
```typescript
|
|
577
|
+
// Upload file
|
|
578
|
+
await client.s3.upload(file);
|
|
579
|
+
|
|
580
|
+
// Download file
|
|
581
|
+
await client.s3.download("path/to/file");
|
|
582
|
+
```
|
|
583
|
+
|
|
584
|
+
## ⚙️ Configuration
|
|
585
|
+
|
|
586
|
+
### Client Options
|
|
587
|
+
|
|
588
|
+
```typescript
|
|
589
|
+
interface AmasterClientOptions {
|
|
590
|
+
/** Base URL for the Amaster API */
|
|
591
|
+
baseURL: string;
|
|
592
|
+
|
|
593
|
+
/** Optional custom headers */
|
|
594
|
+
headers?: Record<string, string>;
|
|
595
|
+
|
|
596
|
+
/** Called when receiving 401 Unauthorized */
|
|
597
|
+
onUnauthorized?: () => void;
|
|
598
|
+
|
|
599
|
+
/** Called when token expires (before auto-refresh) */
|
|
600
|
+
onTokenExpired?: () => void;
|
|
601
|
+
|
|
602
|
+
/** Enable automatic token refresh (default: true) */
|
|
603
|
+
autoRefresh?: boolean;
|
|
604
|
+
|
|
605
|
+
/** Refresh threshold in seconds (default: 300) */
|
|
606
|
+
refreshThreshold?: number;
|
|
607
|
+
|
|
608
|
+
/** Automatically handle OAuth callback on initialization (default: true) */
|
|
609
|
+
autoHandleOAuthCallback?: boolean;
|
|
610
|
+
}
|
|
611
|
+
```
|
|
612
|
+
|
|
613
|
+
### Example with All Options
|
|
614
|
+
|
|
615
|
+
```typescript
|
|
616
|
+
const client = createClient({
|
|
617
|
+
baseURL: "https://api.amaster.ai",
|
|
618
|
+
|
|
619
|
+
headers: {
|
|
620
|
+
"X-App-Version": "1.0.0",
|
|
621
|
+
},
|
|
622
|
+
|
|
623
|
+
onUnauthorized: () => {
|
|
624
|
+
console.log("Session expired, redirecting to login...");
|
|
625
|
+
window.location.href = "/login";
|
|
626
|
+
},
|
|
627
|
+
|
|
628
|
+
onTokenExpired: () => {
|
|
629
|
+
console.log("Token expired, will auto-refresh");
|
|
630
|
+
},
|
|
631
|
+
|
|
632
|
+
autoRefresh: true,
|
|
633
|
+
refreshThreshold: 300, // Refresh 5 minutes before expiry
|
|
634
|
+
});
|
|
635
|
+
```
|
|
636
|
+
|
|
637
|
+
## 🔧 Advanced Usage
|
|
638
|
+
|
|
639
|
+
### Manual Token Management
|
|
640
|
+
|
|
641
|
+
```typescript
|
|
642
|
+
// Get current access token
|
|
643
|
+
const token = client.getAccessToken();
|
|
644
|
+
|
|
645
|
+
// Set token manually (useful for SSR or external auth)
|
|
646
|
+
client.setAccessToken("your-jwt-token");
|
|
647
|
+
|
|
648
|
+
// Clear all auth data
|
|
649
|
+
client.clearAuth();
|
|
650
|
+
```
|
|
651
|
+
|
|
652
|
+
### Error Handling
|
|
653
|
+
|
|
654
|
+
```typescript
|
|
655
|
+
const result = await client.entity.list("default", "users");
|
|
656
|
+
|
|
657
|
+
if (result.success) {
|
|
658
|
+
// Success case
|
|
659
|
+
console.log("Data:", result.data);
|
|
660
|
+
} else {
|
|
661
|
+
// Error case
|
|
662
|
+
console.error("Error:", result.error);
|
|
663
|
+
console.error("Status:", result.statusCode);
|
|
664
|
+
}
|
|
665
|
+
```
|
|
666
|
+
|
|
667
|
+
### Custom HTTP Requests
|
|
668
|
+
|
|
669
|
+
```typescript
|
|
670
|
+
// Make a custom request with automatic auth
|
|
671
|
+
const { data, error } = await client.http.request({
|
|
672
|
+
url: "/custom/endpoint",
|
|
673
|
+
method: "POST",
|
|
674
|
+
data: { key: "value" },
|
|
675
|
+
});
|
|
676
|
+
```
|
|
677
|
+
|
|
678
|
+
## 🎨 Comparison with Individual Clients
|
|
679
|
+
|
|
680
|
+
### Before (Using separate clients)
|
|
681
|
+
|
|
682
|
+
```typescript
|
|
683
|
+
import { createAuthClient } from "@amaster.ai/auth-client";
|
|
684
|
+
import { createEntityClient } from "@amaster.ai/entity-client";
|
|
685
|
+
import { createBpmClient } from "@amaster.ai/bpm-client";
|
|
686
|
+
|
|
687
|
+
const authClient = createAuthClient({ baseURL });
|
|
688
|
+
const entityClient = createEntityClient({ baseURL });
|
|
689
|
+
const bpmClient = createBpmClient({ baseURL });
|
|
690
|
+
|
|
691
|
+
// Need to manage tokens manually across clients
|
|
692
|
+
await authClient.login({ email, password });
|
|
693
|
+
const token = authClient.getAccessToken();
|
|
694
|
+
|
|
695
|
+
// Pass token to other clients somehow...
|
|
696
|
+
```
|
|
697
|
+
|
|
698
|
+
### After (Using unified client)
|
|
699
|
+
|
|
700
|
+
```typescript
|
|
701
|
+
import { createClient } from "@amaster.ai/client";
|
|
702
|
+
|
|
703
|
+
const client = createClient({ baseURL });
|
|
704
|
+
|
|
705
|
+
// One client, automatic token management
|
|
706
|
+
await client.auth.login({ email, password });
|
|
707
|
+
await client.entity.list("default", "users"); // Token automatically attached
|
|
708
|
+
await client.bpm.getMyTasks(); // Token automatically attached
|
|
709
|
+
```
|
|
710
|
+
|
|
711
|
+
## 📖 API Reference
|
|
712
|
+
|
|
713
|
+
### `client.auth`
|
|
714
|
+
|
|
715
|
+
Full authentication API from `@amaster.ai/auth-client`:
|
|
716
|
+
|
|
717
|
+
- `login(params)` - Email/password or code-based login
|
|
718
|
+
- `register(params)` - User registration
|
|
719
|
+
- `logout()` - User logout
|
|
720
|
+
- `getMe()` - Get current user profile
|
|
721
|
+
- `updateMe(params)` - Update current user
|
|
722
|
+
- `changePassword(params)` - Change password
|
|
723
|
+
- `refreshToken()` - Manually refresh token
|
|
724
|
+
- `sendCode(params)` - Send verification code
|
|
725
|
+
- `hasPermission(permission)` - Check user permission
|
|
726
|
+
- `hasRole(role)` - Check user role
|
|
727
|
+
|
|
728
|
+
### `client.entity`
|
|
729
|
+
|
|
730
|
+
Full CRUD API from `@amaster.ai/entity-client`:
|
|
731
|
+
|
|
732
|
+
- `list(source, entity, params?)` - List entities with pagination
|
|
733
|
+
- `get(source, entity, id)` - Get single entity
|
|
734
|
+
- `create(source, entity, data)` - Create new entity
|
|
735
|
+
- `update(source, entity, id, data)` - Update entity
|
|
736
|
+
- `delete(source, entity, id)` - Delete entity
|
|
737
|
+
- `bulkUpdate(source, entity, items)` - Bulk update
|
|
738
|
+
- `bulkDelete(source, entity, ids)` - Bulk delete
|
|
739
|
+
- `options(source, entity, fields?)` - Get field options
|
|
740
|
+
|
|
741
|
+
### `client.bpm`
|
|
742
|
+
|
|
743
|
+
Full BPM API from `@amaster.ai/bpm-client`:
|
|
744
|
+
|
|
745
|
+
- `startProcess(params)` - Start process instance
|
|
746
|
+
- `getMyTasks(params?)` - Get current user's tasks
|
|
747
|
+
- `completeTask(taskId, variables?)` - Complete a task
|
|
748
|
+
- `claimTask(taskId)` - Claim a task
|
|
749
|
+
- `unclaimTask(taskId)` - Unclaim a task
|
|
750
|
+
- And more...
|
|
751
|
+
|
|
752
|
+
### `client.workflow`
|
|
753
|
+
|
|
754
|
+
Workflow execution API from `@amaster.ai/workflow-client`:
|
|
755
|
+
|
|
756
|
+
- `execute(workflowId, params)` - Execute a workflow
|
|
757
|
+
- `getStatus(executionId)` - Get execution status
|
|
758
|
+
- And more...
|
|
759
|
+
|
|
760
|
+
### `client.asr`
|
|
761
|
+
|
|
762
|
+
WebSocket real-time speech recognition:
|
|
763
|
+
|
|
764
|
+
- `connect()` - Connect to ASR service
|
|
765
|
+
- `startRecording()` - Start microphone recording
|
|
766
|
+
- `stopRecording()` - Stop recording
|
|
767
|
+
- `close()` - Close connection
|
|
768
|
+
|
|
769
|
+
### `client.asrHttp`
|
|
770
|
+
|
|
771
|
+
HTTP press-to-talk speech recognition:
|
|
772
|
+
|
|
773
|
+
- `startRecording()` - Start recording
|
|
774
|
+
- `stopRecording()` - Stop and get result
|
|
775
|
+
- `recognizeFile(file)` - Recognize audio file
|
|
776
|
+
- `recognizeUrl(url)` - Recognize audio URL
|
|
777
|
+
|
|
778
|
+
### `client.tts`
|
|
779
|
+
|
|
780
|
+
WebSocket real-time text-to-speech:
|
|
781
|
+
|
|
782
|
+
- `connect()` - Connect to TTS service
|
|
783
|
+
- `speak(text)` - Synthesize and play speech
|
|
784
|
+
- `play()` - Manually play audio
|
|
785
|
+
- `close()` - Close connection
|
|
786
|
+
|
|
787
|
+
### `client.copilot`
|
|
788
|
+
|
|
789
|
+
AI assistant API:
|
|
790
|
+
|
|
791
|
+
- `sendMessage(messages, options?)` - Send messages to AI
|
|
792
|
+
|
|
793
|
+
### `client.function`
|
|
794
|
+
|
|
795
|
+
Function invocation API:
|
|
796
|
+
|
|
797
|
+
- `invoke<T>(funcName, params?)` - Invoke a serverless function
|
|
798
|
+
|
|
799
|
+
### `client.s3`
|
|
800
|
+
|
|
801
|
+
S3 storage API:
|
|
802
|
+
|
|
803
|
+
- `upload(file)` - Upload file
|
|
804
|
+
- `download(path)` - Download file
|
|
805
|
+
|
|
806
|
+
## 🔐 Token Management Flow
|
|
807
|
+
|
|
808
|
+
```
|
|
809
|
+
1. Login → Token stored automatically
|
|
810
|
+
2. Request → Token attached to headers
|
|
811
|
+
3. Response 401 → onUnauthorized() called
|
|
812
|
+
4. Token near expiry → Auto-refresh (if enabled)
|
|
813
|
+
5. Logout → Token cleared
|
|
814
|
+
```
|
|
815
|
+
|
|
816
|
+
## 🌐 Environment Support
|
|
817
|
+
|
|
818
|
+
Works in:
|
|
819
|
+
|
|
820
|
+
- ✅ Browser (modern)
|
|
821
|
+
- ✅ Node.js (18+)
|
|
822
|
+
- ✅ React / Vue / Angular
|
|
823
|
+
- ✅ Next.js / Nuxt
|
|
824
|
+
- ✅ React Native (with axios)
|
|
825
|
+
|
|
826
|
+
## 📄 License
|
|
827
|
+
|
|
828
|
+
MIT © Amaster Team
|
|
829
|
+
|
|
830
|
+
## 🤝 Related Packages
|
|
831
|
+
|
|
832
|
+
All these packages are now integrated into `@amaster.ai/client`:
|
|
833
|
+
|
|
834
|
+
- `@amaster.ai/auth-client` - Authentication (login, register, etc.)
|
|
835
|
+
- `@amaster.ai/entity-client` - Entity CRUD operations
|
|
836
|
+
- `@amaster.ai/bpm-client` - Business Process Management
|
|
837
|
+
- `@amaster.ai/workflow-client` - Workflow execution
|
|
838
|
+
- `@amaster.ai/asr-client` - Speech recognition (WebSocket + HTTP)
|
|
839
|
+
- `@amaster.ai/copilot-client` - AI assistant / chatbot
|
|
840
|
+
- `@amaster.ai/function-client` - Function invocation
|
|
841
|
+
- `@amaster.ai/tts-client` - Text-to-speech (WebSocket)
|
|
842
|
+
- `@amaster.ai/s3-client` - S3 storage operations
|
|
843
|
+
- `@amaster.ai/http-client` - HTTP client foundation (internal)
|
|
844
|
+
|
|
845
|
+
## 💡 Inspiration
|
|
846
|
+
|
|
847
|
+
API design inspired by [Supabase](https://supabase.com) - aiming for the same level of developer experience and simplicity.
|