@siduri-x/api 1.0.0 → 1.0.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/dist/app.js +181 -137
- package/dist/b0-b6.test.js +1 -1
- package/dist/cors.d.ts +3 -0
- package/dist/cors.js +42 -0
- package/dist/index.js +3 -3
- package/dist/index.test.js +1 -1
- package/dist/t6-security.test.js +191 -1
- package/package.json +12 -12
- package/src/app.ts +184 -147
- package/src/b0-b6.test.ts +1 -1
- package/src/cors.ts +44 -0
- package/src/index.test.ts +1 -1
- package/src/index.ts +4 -4
- package/src/t6-security.test.ts +210 -1
package/src/app.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import express, { Express } from 'express';
|
|
2
2
|
import cors from 'cors';
|
|
3
|
-
import {
|
|
3
|
+
import { createCorsOptions } from './cors';
|
|
4
|
+
import { SiduriRuntime, dispatchCompanionChat } from './runtime';
|
|
4
5
|
import { OpenAICompatibleBrain, OpenRouterBrain } from '@siduri-x/brain';
|
|
5
6
|
import { PostgresMemoryOrgan } from '@siduri-x/memory';
|
|
6
|
-
import {
|
|
7
|
+
import { VoiceAdapter } from '@siduri-x/voice';
|
|
7
8
|
import { EKnowledgeAdapter } from '@siduri-x/knowledge';
|
|
8
9
|
import { OpenRouterVisionAdapter } from '@siduri-x/vision';
|
|
9
10
|
import { ActiveSelfCompiler } from '@siduri-x/behavior';
|
|
@@ -22,7 +23,7 @@ export interface AppInstance {
|
|
|
22
23
|
|
|
23
24
|
export function createApp(runtimes: Map<string, SiduriRuntime> = new Map()): AppInstance {
|
|
24
25
|
const app: Express = express();
|
|
25
|
-
app.use(cors());
|
|
26
|
+
app.use(cors(createCorsOptions()));
|
|
26
27
|
app.use(express.json());
|
|
27
28
|
|
|
28
29
|
let observationOrgan: FixtureObservationOrgan | undefined;
|
|
@@ -48,7 +49,7 @@ export function createApp(runtimes: Map<string, SiduriRuntime> = new Map()): App
|
|
|
48
49
|
function createVoice(config: any) {
|
|
49
50
|
return isDisabled(config)
|
|
50
51
|
? undefined
|
|
51
|
-
: new
|
|
52
|
+
: new VoiceAdapter({ provider: config.provider || 'voicevox', baseUrl: process.env.VOICEVOX_URL || 'http://localhost:50021', speakerId: config.speakerId || 1 });
|
|
52
53
|
}
|
|
53
54
|
|
|
54
55
|
function createKnowledge(config: any) {
|
|
@@ -113,11 +114,19 @@ export function createApp(runtimes: Map<string, SiduriRuntime> = new Map()): App
|
|
|
113
114
|
|
|
114
115
|
// STATUS / HEALTH ENDPOINTS
|
|
115
116
|
app.get('/health', (req, res) => res.json({ status: "ok" }));
|
|
116
|
-
app.get('/version', (req, res) => res.json({ name: "siduri-
|
|
117
|
-
app.get('/ready', (req, res) =>
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
117
|
+
app.get('/version', (req, res) => res.json({ name: "siduri-x-api", version: "0.2.0-x" }));
|
|
118
|
+
app.get('/ready', (req, res) => {
|
|
119
|
+
const isReady = runtimes.size > 0;
|
|
120
|
+
res.status(isReady ? 200 : 503).json({
|
|
121
|
+
status: isReady ? "ready" : "not_ready",
|
|
122
|
+
companionCount: runtimes.size,
|
|
123
|
+
});
|
|
124
|
+
});
|
|
125
|
+
app.get('/voice/health', (req, res) => {
|
|
126
|
+
const hasVoice = Array.from(runtimes.values()).some((r) => Boolean(r.voice));
|
|
127
|
+
res.json({ provider: "siduri-voice", configured: hasVoice });
|
|
128
|
+
});
|
|
129
|
+
app.get('/obs/health', (req, res) => res.json({ connected: Boolean(observationOrgan) }));
|
|
121
130
|
app.get('/me', attachIdentity, (req, res) => {
|
|
122
131
|
const identity = (req as any).identity as Identity;
|
|
123
132
|
res.json({
|
|
@@ -133,12 +142,20 @@ export function createApp(runtimes: Map<string, SiduriRuntime> = new Map()): App
|
|
|
133
142
|
const { id, message, history } = req.body;
|
|
134
143
|
const identity = (req as any).identity as Identity;
|
|
135
144
|
|
|
145
|
+
// Single-owner companion model: /chat defaults to OWNER identity.
|
|
146
|
+
// Explicit non-owner role in request body or context (e.g. adversarial test suites) is respected.
|
|
147
|
+
const effectiveRole = req.body?.role === 'VIEWER' || req.body?.context?.actor?.authorizationRole === 'viewer'
|
|
148
|
+
? 'VIEWER'
|
|
149
|
+
: (identity?.role === 'OPERATOR' ? 'OPERATOR' : 'OWNER');
|
|
150
|
+
const isOwner = effectiveRole === 'OWNER';
|
|
151
|
+
|
|
136
152
|
// Call context mapper at the API boundary
|
|
137
153
|
const mappingResult = mapRequestContext(
|
|
138
154
|
{
|
|
139
155
|
...req.body,
|
|
140
156
|
id: id || req.body.companionId,
|
|
141
|
-
role:
|
|
157
|
+
role: effectiveRole,
|
|
158
|
+
authenticated: isOwner,
|
|
142
159
|
generateCorrelationId: true,
|
|
143
160
|
},
|
|
144
161
|
{
|
|
@@ -159,15 +176,13 @@ export function createApp(runtimes: Map<string, SiduriRuntime> = new Map()): App
|
|
|
159
176
|
if (!runtime) return res.status(404).json({ error: "Companion not found" });
|
|
160
177
|
|
|
161
178
|
try {
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
const response = await runtime.handleUserMessage(message, legacyScope, history);
|
|
179
|
+
const response = await dispatchCompanionChat(runtime, {
|
|
180
|
+
id: companionId,
|
|
181
|
+
companionId,
|
|
182
|
+
message,
|
|
183
|
+
context: mappingResult.context,
|
|
184
|
+
history,
|
|
185
|
+
});
|
|
171
186
|
res.json(response);
|
|
172
187
|
} catch (e: any) {
|
|
173
188
|
res.status(500).json({ error: e.message });
|
|
@@ -228,7 +243,24 @@ export function createApp(runtimes: Map<string, SiduriRuntime> = new Map()): App
|
|
|
228
243
|
});
|
|
229
244
|
|
|
230
245
|
// MEMORY MUTATIONS - PROPOSALS
|
|
231
|
-
app.post('/memory/proposals/update', requireRole(['OWNER', 'OPERATOR']), async (req, res) =>
|
|
246
|
+
app.post('/memory/proposals/update', requireRole(['OWNER', 'OPERATOR']), async (req, res) => {
|
|
247
|
+
const id = req.body.companionId as string || Array.from(runtimes.keys())[0];
|
|
248
|
+
const runtime = runtimes.get(id);
|
|
249
|
+
if (!runtime) return res.status(404).json({ error: "Companion not found" });
|
|
250
|
+
if (!runtime.memory || typeof runtime.memory.updateClaim !== 'function') {
|
|
251
|
+
return res.status(400).json({ error: "Memory organ does not support updating claims" });
|
|
252
|
+
}
|
|
253
|
+
try {
|
|
254
|
+
const claimId = req.body.id || req.body.claimId;
|
|
255
|
+
if (!claimId) {
|
|
256
|
+
return res.status(400).json({ error: "Missing required claim id" });
|
|
257
|
+
}
|
|
258
|
+
const updated = await runtime.memory.updateClaim(claimId, req.body.updates || req.body);
|
|
259
|
+
res.json({ success: true, claim: updated });
|
|
260
|
+
} catch (e: any) {
|
|
261
|
+
res.status(500).json({ error: e.message });
|
|
262
|
+
}
|
|
263
|
+
});
|
|
232
264
|
|
|
233
265
|
app.post('/memory/proposals/approve', requireRole(['OWNER', 'OPERATOR']), async (req, res) => {
|
|
234
266
|
const id = req.body.companionId as string || Array.from(runtimes.keys())[0];
|
|
@@ -309,151 +341,156 @@ export function createApp(runtimes: Map<string, SiduriRuntime> = new Map()): App
|
|
|
309
341
|
}
|
|
310
342
|
});
|
|
311
343
|
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
344
|
+
const isDevMode = process.env.NODE_ENV !== 'production' || process.env.SIDURI_DEV_MODE === 'true';
|
|
345
|
+
if (isDevMode) {
|
|
346
|
+
app.post('/dev/memory/reset', requireRole(['OWNER']), async (req, res) => {
|
|
347
|
+
const id = req.body.companionId as string || Array.from(runtimes.keys())[0];
|
|
348
|
+
const runtime = runtimes.get(id);
|
|
349
|
+
if (!runtime) return res.status(404).json({ error: "Companion not found" });
|
|
350
|
+
if (!runtime.memory || typeof runtime.memory.resetMemory !== 'function') {
|
|
351
|
+
return res.status(400).json({ error: "Memory organ does not support reset" });
|
|
352
|
+
}
|
|
353
|
+
try {
|
|
354
|
+
await runtime.memory.resetMemory();
|
|
355
|
+
res.json({ reset: true });
|
|
356
|
+
} catch (e: any) {
|
|
357
|
+
res.status(500).json({ error: e.message });
|
|
358
|
+
}
|
|
359
|
+
});
|
|
319
360
|
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
361
|
+
app.post('/dev/mock-response', async (req, res) => {
|
|
362
|
+
const companionId = req.body?.companionId || Array.from(runtimes.keys())[0] || 'default';
|
|
363
|
+
const runtime = runtimes.get(companionId);
|
|
364
|
+
if (!runtime) return res.status(404).json({ accepted: false, error: 'Companion not found' });
|
|
365
|
+
const staged = runtime.gating.stageResponse({
|
|
366
|
+
requestContext: {
|
|
367
|
+
companionId,
|
|
368
|
+
actor: {
|
|
369
|
+
actorId: 'operator-a',
|
|
370
|
+
sessionId: 'sess-op',
|
|
371
|
+
authorizationRole: 'operator',
|
|
372
|
+
capabilities: ['chat:public', 'memory:approve'],
|
|
373
|
+
authenticated: true,
|
|
374
|
+
},
|
|
375
|
+
conversation: {
|
|
376
|
+
channel: 'public',
|
|
377
|
+
audienceId: 'audience-public',
|
|
378
|
+
correlationId: req.body?.correlation_id || `corr-${Date.now()}`,
|
|
379
|
+
},
|
|
333
380
|
},
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
staged: true,
|
|
347
|
-
status: staged.status,
|
|
348
|
-
response_id: staged.responseId,
|
|
349
|
-
correlation_id: staged.correlationId,
|
|
350
|
-
speech: staged.speech,
|
|
381
|
+
candidateSpeech: req.body?.speech || 'Mocked staged response for review',
|
|
382
|
+
candidateLanguage: req.body?.language || 'en',
|
|
383
|
+
requiresApproval: req.body?.requiresApproval ?? true,
|
|
384
|
+
});
|
|
385
|
+
res.json({
|
|
386
|
+
accepted: true,
|
|
387
|
+
staged: true,
|
|
388
|
+
status: staged.status,
|
|
389
|
+
response_id: staged.responseId,
|
|
390
|
+
correlation_id: staged.correlationId,
|
|
391
|
+
speech: staged.speech,
|
|
392
|
+
});
|
|
351
393
|
});
|
|
352
|
-
});
|
|
353
|
-
|
|
354
|
-
app.post('/dev/approve-response', async (req, res) => {
|
|
355
|
-
const companionId = req.body?.companionId || Array.from(runtimes.keys())[0] || 'default';
|
|
356
|
-
const runtime = runtimes.get(companionId);
|
|
357
|
-
if (!runtime) return res.status(404).json({ approved: false, error: 'Companion not found' });
|
|
358
|
-
|
|
359
|
-
let responseId = req.body?.responseId;
|
|
360
|
-
let correlationId = req.body?.correlation_id;
|
|
361
394
|
|
|
362
|
-
|
|
363
|
-
const
|
|
364
|
-
|
|
365
|
-
|
|
395
|
+
app.post('/dev/approve-response', async (req, res) => {
|
|
396
|
+
const companionId = req.body?.companionId || Array.from(runtimes.keys())[0] || 'default';
|
|
397
|
+
const runtime = runtimes.get(companionId);
|
|
398
|
+
if (!runtime) return res.status(404).json({ approved: false, error: 'Companion not found' });
|
|
399
|
+
|
|
400
|
+
let responseId = req.body?.responseId;
|
|
401
|
+
let correlationId = req.body?.correlation_id;
|
|
402
|
+
|
|
403
|
+
if (!responseId && correlationId) {
|
|
404
|
+
const found = runtime.gating.findStagedPlanByCorrelation(companionId, correlationId);
|
|
405
|
+
if (found) {
|
|
406
|
+
responseId = found.responseId;
|
|
407
|
+
}
|
|
408
|
+
} else if (responseId && !correlationId) {
|
|
409
|
+
const found = runtime.gating.getStagedPlan(responseId);
|
|
410
|
+
if (found) {
|
|
411
|
+
correlationId = found.correlationId;
|
|
412
|
+
}
|
|
366
413
|
}
|
|
367
|
-
} else if (responseId && !correlationId) {
|
|
368
|
-
const found = runtime.gating.getStagedPlan(responseId);
|
|
369
|
-
if (found) {
|
|
370
|
-
correlationId = found.correlationId;
|
|
371
|
-
}
|
|
372
|
-
}
|
|
373
414
|
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
415
|
+
if (!responseId) {
|
|
416
|
+
return res.status(400).json({ approved: false, error: 'UNKNOWN_APPROVAL_ID' });
|
|
417
|
+
}
|
|
377
418
|
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
419
|
+
const result = runtime.gating.approveResponse({
|
|
420
|
+
responseId,
|
|
421
|
+
companionId,
|
|
422
|
+
correlationId: correlationId || '',
|
|
423
|
+
audienceId: req.body?.audienceId,
|
|
424
|
+
});
|
|
384
425
|
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
426
|
+
if (!result.success) {
|
|
427
|
+
return res.status(400).json({ approved: false, error: result.reason });
|
|
428
|
+
}
|
|
388
429
|
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
430
|
+
// Now evaluated as approved
|
|
431
|
+
const evaluation = runtime.gating.evaluateGate(result.plan!);
|
|
432
|
+
res.json({
|
|
433
|
+
approved: true,
|
|
434
|
+
status: evaluation.disposition,
|
|
435
|
+
response_id: result.plan!.responseId,
|
|
436
|
+
speech: result.plan!.speech,
|
|
437
|
+
language: result.plan!.language,
|
|
438
|
+
});
|
|
397
439
|
});
|
|
398
|
-
});
|
|
399
440
|
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
441
|
+
app.post('/dev/reject-response', async (req, res) => {
|
|
442
|
+
const companionId = req.body?.companionId || Array.from(runtimes.keys())[0] || 'default';
|
|
443
|
+
const runtime = runtimes.get(companionId);
|
|
444
|
+
if (!runtime) return res.status(404).json({ rejected: false, error: 'Companion not found' });
|
|
445
|
+
|
|
446
|
+
let responseId = req.body?.responseId;
|
|
447
|
+
let correlationId = req.body?.correlation_id;
|
|
448
|
+
|
|
449
|
+
if (!responseId && correlationId) {
|
|
450
|
+
const found = runtime.gating.findStagedPlanByCorrelation(companionId, correlationId);
|
|
451
|
+
if (found) {
|
|
452
|
+
responseId = found.responseId;
|
|
453
|
+
}
|
|
454
|
+
} else if (responseId && !correlationId) {
|
|
455
|
+
const found = runtime.gating.getStagedPlan(responseId);
|
|
456
|
+
if (found) {
|
|
457
|
+
correlationId = found.correlationId;
|
|
458
|
+
}
|
|
417
459
|
}
|
|
418
|
-
}
|
|
419
460
|
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
461
|
+
if (!responseId) {
|
|
462
|
+
return res.status(400).json({ rejected: false, error: 'UNKNOWN_APPROVAL_ID' });
|
|
463
|
+
}
|
|
423
464
|
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
465
|
+
const result = runtime.gating.rejectResponse({
|
|
466
|
+
responseId,
|
|
467
|
+
companionId,
|
|
468
|
+
correlationId: correlationId || '',
|
|
469
|
+
reason: req.body?.reason,
|
|
470
|
+
});
|
|
430
471
|
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
472
|
+
if (!result.success) {
|
|
473
|
+
return res.status(400).json({ rejected: false, error: result.reason });
|
|
474
|
+
}
|
|
434
475
|
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
476
|
+
res.json({
|
|
477
|
+
rejected: true,
|
|
478
|
+
status: result.plan!.status,
|
|
479
|
+
response_id: result.plan!.responseId,
|
|
480
|
+
});
|
|
439
481
|
});
|
|
440
|
-
});
|
|
441
|
-
|
|
442
|
-
app.post('/dev/mock-observation', async (req, res) => {
|
|
443
|
-
if (!observationOrgan) return res.status(503).json({ accepted: false, reason: 'observation_unavailable' });
|
|
444
|
-
const result = await observationOrgan.ingest(
|
|
445
|
-
new Uint8Array([115, 121, 110, 116, 104, 101, 116, 105, 99]),
|
|
446
|
-
'fixture-observation',
|
|
447
|
-
'configured-vision',
|
|
448
|
-
);
|
|
449
|
-
if (!result.observation) return res.status(result.duplicate ? 200 : 409).json({ accepted: false, ...result });
|
|
450
|
-
res.status(202).json({ accepted: true, observation: result.observation });
|
|
451
|
-
});
|
|
452
482
|
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
483
|
+
app.post('/dev/mock-observation', async (req, res) => {
|
|
484
|
+
if (!observationOrgan) return res.status(503).json({ accepted: false, reason: 'observation_unavailable' });
|
|
485
|
+
const result = await observationOrgan.ingest(
|
|
486
|
+
new Uint8Array([115, 121, 110, 116, 104, 101, 116, 105, 99]),
|
|
487
|
+
'fixture-observation',
|
|
488
|
+
'configured-vision',
|
|
489
|
+
);
|
|
490
|
+
if (!result.observation) return res.status(result.duplicate ? 200 : 409).json({ accepted: false, ...result });
|
|
491
|
+
res.status(202).json({ accepted: true, observation: result.observation });
|
|
492
|
+
});
|
|
493
|
+
}
|
|
457
494
|
|
|
458
495
|
return { app, runtimes, setObservationOrgan: (org: FixtureObservationOrgan) => { observationOrgan = org; } };
|
|
459
496
|
}
|
package/src/b0-b6.test.ts
CHANGED
package/src/cors.ts
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import cors from 'cors';
|
|
2
|
+
|
|
3
|
+
export function getAllowedOrigins(): Set<string> {
|
|
4
|
+
const allowed = new Set<string>([
|
|
5
|
+
'http://localhost:3000',
|
|
6
|
+
'http://127.0.0.1:3000',
|
|
7
|
+
'http://localhost:3001',
|
|
8
|
+
'http://127.0.0.1:3001',
|
|
9
|
+
]);
|
|
10
|
+
|
|
11
|
+
if (process.env.PORT) {
|
|
12
|
+
allowed.add(`http://localhost:${process.env.PORT}`);
|
|
13
|
+
allowed.add(`http://127.0.0.1:${process.env.PORT}`);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const envOrigins = process.env.ALLOWED_ORIGINS;
|
|
17
|
+
if (envOrigins) {
|
|
18
|
+
for (const origin of envOrigins.split(',')) {
|
|
19
|
+
const trimmed = origin.trim();
|
|
20
|
+
if (trimmed) {
|
|
21
|
+
allowed.add(trimmed);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return allowed;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function createCorsOptions(): cors.CorsOptions {
|
|
30
|
+
return {
|
|
31
|
+
origin: (origin, callback) => {
|
|
32
|
+
// Allow non-browser requests with no origin header (e.g., native tools, curl)
|
|
33
|
+
if (!origin) {
|
|
34
|
+
return callback(null, true);
|
|
35
|
+
}
|
|
36
|
+
const allowedOrigins = getAllowedOrigins();
|
|
37
|
+
if (allowedOrigins.has(origin)) {
|
|
38
|
+
return callback(null, true);
|
|
39
|
+
}
|
|
40
|
+
return callback(null, false);
|
|
41
|
+
},
|
|
42
|
+
credentials: true,
|
|
43
|
+
};
|
|
44
|
+
}
|
package/src/index.test.ts
CHANGED
package/src/index.ts
CHANGED
|
@@ -5,7 +5,7 @@ import { createApp, AppInstance } from './app';
|
|
|
5
5
|
import { SiduriRuntime } from './runtime';
|
|
6
6
|
import { OpenAICompatibleBrain, OpenRouterBrain } from '@siduri-x/brain';
|
|
7
7
|
import { PostgresMemoryOrgan } from '@siduri-x/memory';
|
|
8
|
-
import {
|
|
8
|
+
import { VoiceAdapter } from '@siduri-x/voice';
|
|
9
9
|
import { EKnowledgeAdapter } from '@siduri-x/knowledge';
|
|
10
10
|
import { OpenRouterVisionAdapter } from '@siduri-x/vision';
|
|
11
11
|
import { ActiveSelfCompiler } from '@siduri-x/behavior';
|
|
@@ -41,7 +41,7 @@ function isDisabled(config: any): boolean {
|
|
|
41
41
|
function createVoice(config: any) {
|
|
42
42
|
return isDisabled(config)
|
|
43
43
|
? undefined
|
|
44
|
-
: new
|
|
44
|
+
: new VoiceAdapter({ provider: config.provider || 'voicevox', baseUrl: process.env.VOICEVOX_URL || 'http://localhost:50021', speakerId: config.speakerId || 1 });
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
function createKnowledge(config: any) {
|
|
@@ -151,8 +151,8 @@ async function bootDefaultCompanion() {
|
|
|
151
151
|
|
|
152
152
|
if (process.env.NODE_ENV !== 'test') {
|
|
153
153
|
bootDefaultCompanion().then(() => {
|
|
154
|
-
app.listen(PORT, () => {
|
|
155
|
-
console.log(`Siduri-
|
|
154
|
+
app.listen(Number(PORT), '127.0.0.1', () => {
|
|
155
|
+
console.log(`Siduri-X API running on port ${PORT} (127.0.0.1)`);
|
|
156
156
|
});
|
|
157
157
|
}).catch(e => {
|
|
158
158
|
console.error("Failed to boot default companion:", e);
|