convoai 1.5.3 → 1.6.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/README.md +36 -9
- package/dist/src/commands/agent/chat.js +2 -4
- package/dist/src/commands/agent/chat.js.map +1 -1
- package/dist/src/commands/agent/join.js +2 -4
- package/dist/src/commands/agent/join.js.map +1 -1
- package/dist/src/commands/dev.d.ts +2 -0
- package/dist/src/commands/dev.js +73 -0
- package/dist/src/commands/dev.js.map +1 -0
- package/dist/src/commands/go.js +3 -8
- package/dist/src/commands/go.js.map +1 -1
- package/dist/src/commands/init.d.ts +2 -0
- package/dist/src/commands/init.js +326 -0
- package/dist/src/commands/init.js.map +1 -0
- package/dist/src/commands/openclaw.js +2 -4
- package/dist/src/commands/openclaw.js.map +1 -1
- package/dist/src/commands/quickstart.js +137 -56
- package/dist/src/commands/quickstart.js.map +1 -1
- package/dist/src/index.js +11 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/starters/web/server/convoai-api.d.ts +42 -0
- package/dist/src/starters/web/server/convoai-api.js +116 -0
- package/dist/src/starters/web/server/convoai-api.js.map +1 -0
- package/dist/src/starters/web/server/index.d.ts +1 -0
- package/dist/src/starters/web/server/index.js +85 -0
- package/dist/src/starters/web/server/index.js.map +1 -0
- package/dist/src/starters/web/server/routes/callback.d.ts +2 -0
- package/dist/src/starters/web/server/routes/callback.js +10 -0
- package/dist/src/starters/web/server/routes/callback.js.map +1 -0
- package/dist/src/starters/web/server/routes/knowledge.d.ts +2 -0
- package/dist/src/starters/web/server/routes/knowledge.js +15 -0
- package/dist/src/starters/web/server/routes/knowledge.js.map +1 -0
- package/dist/src/starters/web/server/routes/session.d.ts +2 -0
- package/dist/src/starters/web/server/routes/session.js +82 -0
- package/dist/src/starters/web/server/routes/session.js.map +1 -0
- package/dist/src/starters/web/server/routes/token.d.ts +2 -0
- package/dist/src/starters/web/server/routes/token.js +19 -0
- package/dist/src/starters/web/server/routes/token.js.map +1 -0
- package/dist/src/web/serve.d.ts +7 -0
- package/dist/src/web/serve.js +42 -0
- package/dist/src/web/serve.js.map +1 -0
- package/package.json +3 -1
- package/src/starters/web/.env.example +28 -0
- package/src/starters/web/README.md +81 -0
- package/src/starters/web/connectors/README.md +35 -0
- package/src/starters/web/frontend/app.js +352 -0
- package/src/starters/web/frontend/index.html +54 -0
- package/src/starters/web/frontend/style.css +241 -0
- package/src/starters/web/package.json +23 -0
- package/src/starters/web/python-server/.env.example +23 -0
- package/src/starters/web/python-server/README.md +37 -0
- package/src/starters/web/python-server/app.py +202 -0
- package/src/starters/web/python-server/requirements.txt +4 -0
- package/src/starters/web/python-server/token_builder.py +99 -0
- package/src/starters/web/server/convoai-api.ts +243 -0
- package/src/starters/web/server/index.ts +109 -0
- package/src/starters/web/server/routes/callback.ts +13 -0
- package/src/starters/web/server/routes/knowledge.ts +19 -0
- package/src/starters/web/server/routes/session.ts +122 -0
- package/src/starters/web/server/routes/token.ts +22 -0
- package/src/starters/web/server/tsconfig.json +14 -0
- package/src/web/chat-client.html +1 -1
- package/src/web/client.html +1 -1
- package/src/web/serve.ts +45 -0
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
// ConvoAI Starter — Express Server
|
|
2
|
+
// Serves frontend static files + Agora RTC SDK + API routes.
|
|
3
|
+
import 'dotenv/config';
|
|
4
|
+
import express from 'express';
|
|
5
|
+
import { readFileSync } from 'node:fs';
|
|
6
|
+
import { join, dirname } from 'node:path';
|
|
7
|
+
import { fileURLToPath } from 'node:url';
|
|
8
|
+
import { createRequire } from 'node:module';
|
|
9
|
+
import sessionRouter from './routes/session.js';
|
|
10
|
+
import tokenRouter from './routes/token.js';
|
|
11
|
+
import callbackRouter from './routes/callback.js';
|
|
12
|
+
import knowledgeRouter from './routes/knowledge.js';
|
|
13
|
+
import { getHistory } from './convoai-api.js';
|
|
14
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
15
|
+
const __dirname = dirname(__filename);
|
|
16
|
+
const require = createRequire(import.meta.url);
|
|
17
|
+
const app = express();
|
|
18
|
+
const PORT = parseInt(process.env.PORT || '3000', 10);
|
|
19
|
+
// ─── Middleware ─────────────────────────────────────────────────────────────
|
|
20
|
+
app.use(express.json());
|
|
21
|
+
// ─── Agora RTC SDK from npm ────────────────────────────────────────────────
|
|
22
|
+
let sdkCache = null;
|
|
23
|
+
app.get('/agora-sdk.js', (_req, res) => {
|
|
24
|
+
if (!sdkCache) {
|
|
25
|
+
const sdkPath = require.resolve('agora-rtc-sdk-ng/AgoraRTC_N-production.js');
|
|
26
|
+
sdkCache = readFileSync(sdkPath);
|
|
27
|
+
}
|
|
28
|
+
res.set({
|
|
29
|
+
'Content-Type': 'application/javascript; charset=utf-8',
|
|
30
|
+
'Content-Length': String(sdkCache.length),
|
|
31
|
+
'Cache-Control': 'public, max-age=86400',
|
|
32
|
+
});
|
|
33
|
+
res.send(sdkCache);
|
|
34
|
+
});
|
|
35
|
+
// ─── API Routes ────────────────────────────────────────────────────────────
|
|
36
|
+
app.use(sessionRouter);
|
|
37
|
+
app.use(tokenRouter);
|
|
38
|
+
app.use(callbackRouter);
|
|
39
|
+
app.use(knowledgeRouter);
|
|
40
|
+
app.get('/health', (_req, res) => {
|
|
41
|
+
res.json({ status: 'ok' });
|
|
42
|
+
});
|
|
43
|
+
// ─── History Proxy ─────────────────────────────────────────────────────────
|
|
44
|
+
app.get('/history', async (req, res) => {
|
|
45
|
+
const agentId = req.query.agentId;
|
|
46
|
+
if (!agentId) {
|
|
47
|
+
res.status(400).json({ error: 'Missing agentId query parameter' });
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
try {
|
|
51
|
+
const appId = process.env.AGORA_APP_ID;
|
|
52
|
+
const customerId = process.env.AGORA_CUSTOMER_ID;
|
|
53
|
+
const customerSecret = process.env.AGORA_CUSTOMER_SECRET;
|
|
54
|
+
const region = process.env.AGORA_REGION || 'global';
|
|
55
|
+
const history = await getHistory(appId, agentId, customerId, customerSecret, region);
|
|
56
|
+
res.json({ history });
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
res.json({ history: [] });
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
// ─── Frontend Static Files ─────────────────────────────────────────────────
|
|
63
|
+
const frontendDir = join(__dirname, '..', 'frontend');
|
|
64
|
+
app.use(express.static(frontendDir));
|
|
65
|
+
// ─── Start Server ──────────────────────────────────────────────────────────
|
|
66
|
+
app.listen(PORT, () => {
|
|
67
|
+
console.log('');
|
|
68
|
+
console.log(` ConvoAI Starter Server running at:`);
|
|
69
|
+
console.log(` -> http://localhost:${PORT}`);
|
|
70
|
+
console.log('');
|
|
71
|
+
console.log(` API routes:`);
|
|
72
|
+
console.log(` POST /session/start Start voice conversation`);
|
|
73
|
+
console.log(` POST /session/stop Stop conversation`);
|
|
74
|
+
console.log(` GET /token Generate RTC token`);
|
|
75
|
+
console.log(` GET /health Health check`);
|
|
76
|
+
console.log('');
|
|
77
|
+
const required = ['AGORA_APP_ID', 'AGORA_APP_CERTIFICATE', 'AGORA_CUSTOMER_ID', 'AGORA_CUSTOMER_SECRET'];
|
|
78
|
+
const missing = required.filter(k => !process.env[k]);
|
|
79
|
+
if (missing.length > 0) {
|
|
80
|
+
console.log(` ⚠ Missing credentials in .env: ${missing.join(', ')}`);
|
|
81
|
+
console.log(` Run "convoai quickstart" to configure, or edit .env manually.`);
|
|
82
|
+
console.log('');
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/starters/web/server/index.ts"],"names":[],"mappings":"AAAA,mCAAmC;AACnC,6DAA6D;AAE7D,OAAO,eAAe,CAAC;AACvB,OAAO,OAAO,MAAM,SAAS,CAAC;AAC9B,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,aAAa,MAAM,qBAAqB,CAAC;AAChD,OAAO,WAAW,MAAM,mBAAmB,CAAC;AAC5C,OAAO,cAAc,MAAM,sBAAsB,CAAC;AAClD,OAAO,eAAe,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAE9C,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AACtC,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAE/C,MAAM,GAAG,GAAG,OAAO,EAAE,CAAC;AACtB,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,MAAM,EAAE,EAAE,CAAC,CAAC;AAEtD,+EAA+E;AAE/E,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;AAExB,8EAA8E;AAE9E,IAAI,QAAQ,GAAkB,IAAI,CAAC;AAEnC,GAAG,CAAC,GAAG,CAAC,eAAe,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE;IACrC,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,2CAA2C,CAAC,CAAC;QAC7E,QAAQ,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC;IACnC,CAAC;IACD,GAAG,CAAC,GAAG,CAAC;QACN,cAAc,EAAE,uCAAuC;QACvD,gBAAgB,EAAE,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC;QACzC,eAAe,EAAE,uBAAuB;KACzC,CAAC,CAAC;IACH,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;AACrB,CAAC,CAAC,CAAC;AAEH,8EAA8E;AAE9E,GAAG,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;AACvB,GAAG,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;AACrB,GAAG,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;AACxB,GAAG,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;AAEzB,GAAG,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE;IAC/B,GAAG,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;AAC7B,CAAC,CAAC,CAAC;AAEH,8EAA8E;AAE9E,GAAG,CAAC,GAAG,CAAC,UAAU,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE;IACrC,MAAM,OAAO,GAAG,GAAG,CAAC,KAAK,CAAC,OAAiB,CAAC;IAC5C,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,iCAAiC,EAAE,CAAC,CAAC;QACnE,OAAO;IACT,CAAC;IAED,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,YAAa,CAAC;QACxC,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAkB,CAAC;QAClD,MAAM,cAAc,GAAG,OAAO,CAAC,GAAG,CAAC,qBAAsB,CAAC;QAC1D,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,QAAQ,CAAC;QAEpD,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,CAAC,CAAC;QACrF,GAAG,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC;IACxB,CAAC;IAAC,MAAM,CAAC;QACP,GAAG,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,CAAC;IAC5B,CAAC;AACH,CAAC,CAAC,CAAC;AAEH,8EAA8E;AAE9E,MAAM,WAAW,GAAG,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC;AACtD,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC;AAErC,8EAA8E;AAE9E,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,GAAG,EAAE;IACpB,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAChB,OAAO,CAAC,GAAG,CAAC,sCAAsC,CAAC,CAAC;IACpD,OAAO,CAAC,GAAG,CAAC,yBAAyB,IAAI,EAAE,CAAC,CAAC;IAC7C,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAChB,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;IAC7B,OAAO,CAAC,GAAG,CAAC,oDAAoD,CAAC,CAAC;IAClE,OAAO,CAAC,GAAG,CAAC,6CAA6C,CAAC,CAAC;IAC3D,OAAO,CAAC,GAAG,CAAC,8CAA8C,CAAC,CAAC;IAC5D,OAAO,CAAC,GAAG,CAAC,wCAAwC,CAAC,CAAC;IACtD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAEhB,MAAM,QAAQ,GAAG,CAAC,cAAc,EAAE,uBAAuB,EAAE,mBAAmB,EAAE,uBAAuB,CAAC,CAAC;IACzG,MAAM,OAAO,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IACtD,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,OAAO,CAAC,GAAG,CAAC,oCAAoC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACtE,OAAO,CAAC,GAAG,CAAC,iEAAiE,CAAC,CAAC;QAC/E,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// Webhook endpoint for ConvoAI Engine callbacks.
|
|
2
|
+
// Customize: add your webhook handling logic here.
|
|
3
|
+
import { Router } from 'express';
|
|
4
|
+
const router = Router();
|
|
5
|
+
router.post('/callback', (req, res) => {
|
|
6
|
+
console.log('[callback] Received webhook:', JSON.stringify(req.body, null, 2));
|
|
7
|
+
res.json({ received: true });
|
|
8
|
+
});
|
|
9
|
+
export default router;
|
|
10
|
+
//# sourceMappingURL=callback.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"callback.js","sourceRoot":"","sources":["../../../../../../src/starters/web/server/routes/callback.ts"],"names":[],"mappings":"AAAA,iDAAiD;AACjD,mDAAmD;AAEnD,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAEjC,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC;AAExB,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;IACpC,OAAO,CAAC,GAAG,CAAC,8BAA8B,EAAE,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IAC/E,GAAG,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;AAC/B,CAAC,CAAC,CAAC;AAEH,eAAe,MAAM,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// Knowledge base query endpoint.
|
|
2
|
+
// Customize: connect your knowledge base, RAG pipeline, or vector DB here.
|
|
3
|
+
import { Router } from 'express';
|
|
4
|
+
const router = Router();
|
|
5
|
+
router.post('/knowledge', (req, res) => {
|
|
6
|
+
const { query } = req.body || {};
|
|
7
|
+
console.log('[knowledge] Query:', query);
|
|
8
|
+
// Customize: replace with your knowledge base integration
|
|
9
|
+
res.json({
|
|
10
|
+
results: [],
|
|
11
|
+
message: 'Knowledge base not configured. Edit server/routes/knowledge.ts to connect yours.',
|
|
12
|
+
});
|
|
13
|
+
});
|
|
14
|
+
export default router;
|
|
15
|
+
//# sourceMappingURL=knowledge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"knowledge.js","sourceRoot":"","sources":["../../../../../../src/starters/web/server/routes/knowledge.ts"],"names":[],"mappings":"AAAA,iCAAiC;AACjC,2EAA2E;AAE3E,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAEjC,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC;AAExB,MAAM,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;IACrC,MAAM,EAAE,KAAK,EAAE,GAAG,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC;IACjC,OAAO,CAAC,GAAG,CAAC,oBAAoB,EAAE,KAAK,CAAC,CAAC;IAEzC,0DAA0D;IAC1D,GAAG,CAAC,IAAI,CAAC;QACP,OAAO,EAAE,EAAE;QACX,OAAO,EAAE,kFAAkF;KAC5F,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,eAAe,MAAM,CAAC"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { Router } from 'express';
|
|
2
|
+
import { startAgent, stopAgent } from '../convoai-api.js';
|
|
3
|
+
const router = Router();
|
|
4
|
+
// In-memory session store (single session for simplicity)
|
|
5
|
+
// Customize: replace with database or Redis for production
|
|
6
|
+
let currentSession = null;
|
|
7
|
+
router.post('/session/start', async (req, res) => {
|
|
8
|
+
try {
|
|
9
|
+
if (currentSession) {
|
|
10
|
+
res.status(409).json({ error: 'Session already active. Stop it first.' });
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
const appId = process.env.AGORA_APP_ID;
|
|
14
|
+
const appCertificate = process.env.AGORA_APP_CERTIFICATE;
|
|
15
|
+
const customerId = process.env.AGORA_CUSTOMER_ID;
|
|
16
|
+
const customerSecret = process.env.AGORA_CUSTOMER_SECRET;
|
|
17
|
+
const region = process.env.AGORA_REGION || 'global';
|
|
18
|
+
const channel = `session-${Date.now().toString(36)}`;
|
|
19
|
+
const clientUid = Math.floor(Math.random() * 90000) + 10000;
|
|
20
|
+
const config = {
|
|
21
|
+
appId,
|
|
22
|
+
appCertificate,
|
|
23
|
+
customerId,
|
|
24
|
+
customerSecret,
|
|
25
|
+
region,
|
|
26
|
+
channel,
|
|
27
|
+
clientUid,
|
|
28
|
+
llm: {
|
|
29
|
+
vendor: process.env.LLM_VENDOR,
|
|
30
|
+
model: process.env.LLM_MODEL,
|
|
31
|
+
apiKey: process.env.LLM_API_KEY,
|
|
32
|
+
url: process.env.LLM_URL,
|
|
33
|
+
style: process.env.LLM_STYLE,
|
|
34
|
+
},
|
|
35
|
+
tts: {
|
|
36
|
+
vendor: process.env.TTS_VENDOR,
|
|
37
|
+
apiKey: process.env.TTS_API_KEY,
|
|
38
|
+
},
|
|
39
|
+
asr: {
|
|
40
|
+
vendor: process.env.ASR_VENDOR,
|
|
41
|
+
language: process.env.ASR_LANGUAGE,
|
|
42
|
+
},
|
|
43
|
+
};
|
|
44
|
+
const result = await startAgent(config);
|
|
45
|
+
currentSession = { agentId: result.agentId, channel: result.channel };
|
|
46
|
+
res.json({
|
|
47
|
+
appId: result.appId,
|
|
48
|
+
channel: result.channel,
|
|
49
|
+
token: result.token,
|
|
50
|
+
uid: result.uid,
|
|
51
|
+
agentId: result.agentId,
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
catch (err) {
|
|
55
|
+
const message = err instanceof Error ? err.message : 'Unknown error';
|
|
56
|
+
console.error('[session/start]', message);
|
|
57
|
+
res.status(500).json({ error: message });
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
router.post('/session/stop', async (req, res) => {
|
|
61
|
+
try {
|
|
62
|
+
if (!currentSession) {
|
|
63
|
+
res.status(404).json({ error: 'No active session' });
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
const appId = process.env.AGORA_APP_ID;
|
|
67
|
+
const customerId = process.env.AGORA_CUSTOMER_ID;
|
|
68
|
+
const customerSecret = process.env.AGORA_CUSTOMER_SECRET;
|
|
69
|
+
const region = process.env.AGORA_REGION || 'global';
|
|
70
|
+
await stopAgent(appId, currentSession.agentId, customerId, customerSecret, region);
|
|
71
|
+
currentSession = null;
|
|
72
|
+
res.json({ status: 'stopped' });
|
|
73
|
+
}
|
|
74
|
+
catch (err) {
|
|
75
|
+
const message = err instanceof Error ? err.message : 'Unknown error';
|
|
76
|
+
console.error('[session/stop]', message);
|
|
77
|
+
currentSession = null;
|
|
78
|
+
res.status(500).json({ error: message });
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
export default router;
|
|
82
|
+
//# sourceMappingURL=session.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.js","sourceRoot":"","sources":["../../../../../../src/starters/web/server/routes/session.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { Router } from 'express';
|
|
2
|
+
import { generateToken } from '../convoai-api.js';
|
|
3
|
+
const router = Router();
|
|
4
|
+
router.get('/token', (req, res) => {
|
|
5
|
+
try {
|
|
6
|
+
const appId = process.env.AGORA_APP_ID;
|
|
7
|
+
const appCertificate = process.env.AGORA_APP_CERTIFICATE;
|
|
8
|
+
const channel = req.query.channel || `ch-${Date.now().toString(36)}`;
|
|
9
|
+
const uid = parseInt(req.query.uid, 10) || 0;
|
|
10
|
+
const token = generateToken(appId, appCertificate, channel, uid);
|
|
11
|
+
res.json({ token, channel, uid });
|
|
12
|
+
}
|
|
13
|
+
catch (err) {
|
|
14
|
+
const message = err instanceof Error ? err.message : 'Unknown error';
|
|
15
|
+
res.status(500).json({ error: message });
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
export default router;
|
|
19
|
+
//# sourceMappingURL=token.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token.js","sourceRoot":"","sources":["../../../../../../src/starters/web/server/routes/token.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAElD,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC;AAExB,MAAM,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;IAChC,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,YAAa,CAAC;QACxC,MAAM,cAAc,GAAG,OAAO,CAAC,GAAG,CAAC,qBAAsB,CAAC;QAC1D,MAAM,OAAO,GAAI,GAAG,CAAC,KAAK,CAAC,OAAkB,IAAI,MAAM,IAAI,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAC;QACjF,MAAM,GAAG,GAAG,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,GAAa,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC;QAEvD,MAAM,KAAK,GAAG,aAAa,CAAC,KAAK,EAAE,cAAc,EAAE,OAAO,EAAE,GAAG,CAAC,CAAC;QAEjE,GAAG,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC;IACpC,CAAC;IAAC,OAAO,GAAY,EAAE,CAAC;QACtB,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC;QACrE,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC;IAC3C,CAAC;AACH,CAAC,CAAC,CAAC;AAEH,eAAe,MAAM,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { IncomingMessage, ServerResponse } from 'node:http';
|
|
2
|
+
/**
|
|
3
|
+
* Returns an HTTP request handler that serves:
|
|
4
|
+
* - `/agora-sdk.js` → Agora RTC SDK from node_modules
|
|
5
|
+
* - Everything else → the provided HTML string
|
|
6
|
+
*/
|
|
7
|
+
export declare function createWebHandler(html: string): (req: IncomingMessage, res: ServerResponse) => void;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared HTTP handler that serves HTML pages + the Agora RTC SDK from npm.
|
|
3
|
+
* Using the npm package (agora-rtc-sdk-ng) instead of CDN ensures each
|
|
4
|
+
* `npm install convoai` counts as an npm download for the SDK.
|
|
5
|
+
*/
|
|
6
|
+
import { readFileSync } from 'node:fs';
|
|
7
|
+
import { createRequire } from 'node:module';
|
|
8
|
+
const require = createRequire(import.meta.url);
|
|
9
|
+
let _sdkCache = null;
|
|
10
|
+
function getSdkContent() {
|
|
11
|
+
if (!_sdkCache) {
|
|
12
|
+
// Resolve the package main entry (exports "." → AgoraRTC_N-production.js)
|
|
13
|
+
// Using the subpath directly would throw ERR_PACKAGE_PATH_NOT_EXPORTED
|
|
14
|
+
const sdkPath = require.resolve('agora-rtc-sdk-ng');
|
|
15
|
+
_sdkCache = readFileSync(sdkPath);
|
|
16
|
+
}
|
|
17
|
+
return _sdkCache;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Returns an HTTP request handler that serves:
|
|
21
|
+
* - `/agora-sdk.js` → Agora RTC SDK from node_modules
|
|
22
|
+
* - Everything else → the provided HTML string
|
|
23
|
+
*/
|
|
24
|
+
export function createWebHandler(html) {
|
|
25
|
+
return (req, res) => {
|
|
26
|
+
const pathname = (req.url || '/').split('?')[0];
|
|
27
|
+
if (pathname === '/agora-sdk.js') {
|
|
28
|
+
const sdk = getSdkContent();
|
|
29
|
+
res.writeHead(200, {
|
|
30
|
+
'Content-Type': 'application/javascript; charset=utf-8',
|
|
31
|
+
'Content-Length': sdk.length,
|
|
32
|
+
'Cache-Control': 'public, max-age=86400',
|
|
33
|
+
});
|
|
34
|
+
res.end(sdk);
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
|
|
38
|
+
res.end(html);
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=serve.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serve.js","sourceRoot":"","sources":["../../../src/web/serve.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAG5C,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAE/C,IAAI,SAAS,GAAkB,IAAI,CAAC;AAEpC,SAAS,aAAa;IACpB,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,0EAA0E;QAC1E,uEAAuE;QACvE,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,kBAAkB,CAAC,CAAC;QACpD,SAAS,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC;IACpC,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAAC,IAAY;IAC3C,OAAO,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;QAClB,MAAM,QAAQ,GAAG,CAAC,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QAChD,IAAI,QAAQ,KAAK,eAAe,EAAE,CAAC;YACjC,MAAM,GAAG,GAAG,aAAa,EAAE,CAAC;YAC5B,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE;gBACjB,cAAc,EAAE,uCAAuC;gBACvD,gBAAgB,EAAE,GAAG,CAAC,MAAM;gBAC5B,eAAe,EAAE,uBAAuB;aACzC,CAAC,CAAC;YACH,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACf,CAAC;aAAM,CAAC;YACN,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,0BAA0B,EAAE,CAAC,CAAC;YACnE,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAChB,CAAC;IACH,CAAC,CAAC;AACJ,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "convoai",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.6.1",
|
|
4
4
|
"description": "CLI for Agora ConvoAI Engine — start, manage, and monitor conversational AI agents",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -37,11 +37,13 @@
|
|
|
37
37
|
"dist",
|
|
38
38
|
"bin",
|
|
39
39
|
"src/web",
|
|
40
|
+
"src/starters",
|
|
40
41
|
"README.md",
|
|
41
42
|
"LICENSE"
|
|
42
43
|
],
|
|
43
44
|
"license": "MIT",
|
|
44
45
|
"dependencies": {
|
|
46
|
+
"agora-rtc-sdk-ng": "^4.24.3",
|
|
45
47
|
"agora-token": "^2.0.5",
|
|
46
48
|
"axios": "^1.7.0",
|
|
47
49
|
"chalk": "^5.3.0",
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Agora Credentials (from https://console.agora.io)
|
|
2
|
+
AGORA_APP_ID=
|
|
3
|
+
AGORA_APP_CERTIFICATE=
|
|
4
|
+
AGORA_CUSTOMER_ID=
|
|
5
|
+
AGORA_CUSTOMER_SECRET=
|
|
6
|
+
|
|
7
|
+
# Region: "global" or "cn"
|
|
8
|
+
AGORA_REGION=global
|
|
9
|
+
|
|
10
|
+
# LLM Configuration
|
|
11
|
+
LLM_VENDOR=openai
|
|
12
|
+
LLM_MODEL=gpt-4o-mini
|
|
13
|
+
LLM_API_KEY=
|
|
14
|
+
LLM_URL=
|
|
15
|
+
LLM_STYLE=openai
|
|
16
|
+
|
|
17
|
+
# TTS Configuration
|
|
18
|
+
TTS_VENDOR=microsoft
|
|
19
|
+
# TTS_PARAMS is a JSON string with all provider-specific params
|
|
20
|
+
# Examples:
|
|
21
|
+
# Microsoft: {"key":"...","region":"eastus","voice_name":"en-US-AndrewMultilingualNeural"}
|
|
22
|
+
# MiniMax: {"key":"...","group_id":"...","model":"speech-02-turbo","voice_setting":{"voice_id":"..."},"url":"wss://api.minimaxi.com/ws/v1/t2a_v2"}
|
|
23
|
+
# ElevenLabs: {"key":"...","base_url":"wss://api.elevenlabs.io/v1","model_id":"eleven_flash_v2_5","voice_id":"pNInz6obpgDQGcFmaJgB"}
|
|
24
|
+
TTS_PARAMS=
|
|
25
|
+
|
|
26
|
+
# ASR Configuration
|
|
27
|
+
ASR_VENDOR=ares
|
|
28
|
+
ASR_LANGUAGE=en-US
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# ConvoAI Web Starter
|
|
2
|
+
|
|
3
|
+
A three-layer starter project for building voice AI applications with Agora ConvoAI Engine.
|
|
4
|
+
|
|
5
|
+
## Quick Start
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install
|
|
9
|
+
convoai dev # or: npm run dev
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
Open http://localhost:3000 and click **Start Conversation**.
|
|
13
|
+
|
|
14
|
+
## Project Structure
|
|
15
|
+
|
|
16
|
+
```
|
|
17
|
+
frontend/ <- Your UI (HTML / JS / CSS — no build step)
|
|
18
|
+
server/ <- Your backend (Express + TypeScript)
|
|
19
|
+
python-server/ <- Alternative Python backend (FastAPI)
|
|
20
|
+
connectors/ <- Future: telephony, text, IoT extensions
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## How to Customize
|
|
24
|
+
|
|
25
|
+
### Change the UI
|
|
26
|
+
Edit files in `frontend/`:
|
|
27
|
+
- `index.html` — page structure
|
|
28
|
+
- `style.css` — colors, layout, theme
|
|
29
|
+
- `app.js` — interaction logic, Agora RTC handling
|
|
30
|
+
|
|
31
|
+
### Add business logic
|
|
32
|
+
Edit files in `server/routes/`:
|
|
33
|
+
- `session.ts` — session start/stop (add auth, rate limiting, logging)
|
|
34
|
+
- `callback.ts` — handle ConvoAI webhooks
|
|
35
|
+
- `knowledge.ts` — connect your knowledge base or RAG pipeline
|
|
36
|
+
|
|
37
|
+
### Add authentication
|
|
38
|
+
Edit `server/index.ts` — add Express middleware before the API routes.
|
|
39
|
+
|
|
40
|
+
### Switch to Python
|
|
41
|
+
See `python-server/README.md`. Same API routes, same frontend.
|
|
42
|
+
|
|
43
|
+
## Architecture
|
|
44
|
+
|
|
45
|
+
```
|
|
46
|
+
[Your Frontend] --> [Your Server] --> [ConvoAI Engine]
|
|
47
|
+
HTML/JS Express/FastAPI Agora Cloud
|
|
48
|
+
Agora RTC SDK Token generation ASR + LLM + TTS
|
|
49
|
+
Voice capture Business logic Voice AI pipeline
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Future connectors plug in at the same server layer:
|
|
53
|
+
```
|
|
54
|
+
[Phone / SIP] --> [Your Server] --> [ConvoAI Engine]
|
|
55
|
+
[IoT Device] --> [Your Server] --> [ConvoAI Engine]
|
|
56
|
+
[IM / Chat App] --> [Your Server] --> [ConvoAI Engine]
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## From Local to Production
|
|
60
|
+
|
|
61
|
+
1. **Local** — `npm run dev` (you are here)
|
|
62
|
+
2. **Deploy server** — push `server/` to your cloud (Railway, Render, AWS, etc.)
|
|
63
|
+
3. **Deploy frontend** — push `frontend/` to CDN or same server
|
|
64
|
+
4. **Update .env** — swap local credentials for production ones
|
|
65
|
+
|
|
66
|
+
No code changes needed. Same architecture scales from laptop to production.
|
|
67
|
+
|
|
68
|
+
## Environment Variables
|
|
69
|
+
|
|
70
|
+
See `.env.example` for the full list. Key variables:
|
|
71
|
+
|
|
72
|
+
| Variable | Required | Description |
|
|
73
|
+
|----------|----------|-------------|
|
|
74
|
+
| AGORA_APP_ID | Yes | From Agora Console |
|
|
75
|
+
| AGORA_APP_CERTIFICATE | Yes | From project settings |
|
|
76
|
+
| AGORA_CUSTOMER_ID | Yes | REST API credentials |
|
|
77
|
+
| AGORA_CUSTOMER_SECRET | Yes | REST API credentials |
|
|
78
|
+
| LLM_VENDOR | Yes | LLM provider (openai, anthropic, etc.) |
|
|
79
|
+
| LLM_API_KEY | Yes | LLM API key |
|
|
80
|
+
| TTS_VENDOR | Yes | TTS provider (microsoft, elevenlabs, etc.) |
|
|
81
|
+
| TTS_API_KEY | Yes | TTS API key |
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# ConvoAI Connectors
|
|
2
|
+
|
|
3
|
+
This directory is reserved for future communication connectors.
|
|
4
|
+
|
|
5
|
+
## Architecture
|
|
6
|
+
|
|
7
|
+
ConvoAI uses a three-layer architecture:
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
[Connector] --> [Customer Server] --> [ConvoAI Engine]
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
New communication capabilities extend through the Connector layer.
|
|
14
|
+
The Customer Server and ConvoAI Engine remain the same.
|
|
15
|
+
|
|
16
|
+
**Web is the first connector** — implemented in `frontend/`.
|
|
17
|
+
|
|
18
|
+
## Planned Connectors
|
|
19
|
+
|
|
20
|
+
### Telephony / SIP (Phase 2)
|
|
21
|
+
Inbound/outbound phone calls via SIP. Connector handles call signaling; server handles business logic.
|
|
22
|
+
|
|
23
|
+
### Text / IM (Phase 3)
|
|
24
|
+
Chat platforms (Slack, WhatsApp, web chat widgets). Connector handles message transport.
|
|
25
|
+
|
|
26
|
+
### Device / Edge (Phase 3)
|
|
27
|
+
IoT devices, smart speakers, embedded systems. Connector handles device communication.
|
|
28
|
+
|
|
29
|
+
## Design Principle
|
|
30
|
+
|
|
31
|
+
Each connector only handles communication transport.
|
|
32
|
+
Business logic stays in the Customer Server.
|
|
33
|
+
AI capabilities stay in ConvoAI Engine.
|
|
34
|
+
|
|
35
|
+
Adding a new connector never requires rewriting your server or AI config.
|