@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/dist/app.js
CHANGED
|
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.createApp = createApp;
|
|
7
7
|
const express_1 = __importDefault(require("express"));
|
|
8
8
|
const cors_1 = __importDefault(require("cors"));
|
|
9
|
+
const cors_2 = require("./cors");
|
|
9
10
|
const runtime_1 = require("./runtime");
|
|
10
11
|
const brain_1 = require("@siduri-x/brain");
|
|
11
12
|
const memory_1 = require("@siduri-x/memory");
|
|
@@ -20,7 +21,7 @@ const auth_1 = require("./auth");
|
|
|
20
21
|
const context_mapper_1 = require("./context-mapper");
|
|
21
22
|
function createApp(runtimes = new Map()) {
|
|
22
23
|
const app = (0, express_1.default)();
|
|
23
|
-
app.use((0, cors_1.default)());
|
|
24
|
+
app.use((0, cors_1.default)((0, cors_2.createCorsOptions)()));
|
|
24
25
|
app.use(express_1.default.json());
|
|
25
26
|
let observationOrgan;
|
|
26
27
|
function createBrain(config) {
|
|
@@ -42,7 +43,7 @@ function createApp(runtimes = new Map()) {
|
|
|
42
43
|
function createVoice(config) {
|
|
43
44
|
return isDisabled(config)
|
|
44
45
|
? undefined
|
|
45
|
-
: new voice_1.
|
|
46
|
+
: new voice_1.VoiceAdapter({ provider: config.provider || 'voicevox', baseUrl: process.env.VOICEVOX_URL || 'http://localhost:50021', speakerId: config.speakerId || 1 });
|
|
46
47
|
}
|
|
47
48
|
function createKnowledge(config) {
|
|
48
49
|
return isDisabled(config) ? undefined : new knowledge_1.EKnowledgeAdapter(config);
|
|
@@ -96,11 +97,19 @@ function createApp(runtimes = new Map()) {
|
|
|
96
97
|
});
|
|
97
98
|
// STATUS / HEALTH ENDPOINTS
|
|
98
99
|
app.get('/health', (req, res) => res.json({ status: "ok" }));
|
|
99
|
-
app.get('/version', (req, res) => res.json({ name: "siduri-
|
|
100
|
-
app.get('/ready', (req, res) =>
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
100
|
+
app.get('/version', (req, res) => res.json({ name: "siduri-x-api", version: "0.2.0-x" }));
|
|
101
|
+
app.get('/ready', (req, res) => {
|
|
102
|
+
const isReady = runtimes.size > 0;
|
|
103
|
+
res.status(isReady ? 200 : 503).json({
|
|
104
|
+
status: isReady ? "ready" : "not_ready",
|
|
105
|
+
companionCount: runtimes.size,
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
app.get('/voice/health', (req, res) => {
|
|
109
|
+
const hasVoice = Array.from(runtimes.values()).some((r) => Boolean(r.voice));
|
|
110
|
+
res.json({ provider: "siduri-voice", configured: hasVoice });
|
|
111
|
+
});
|
|
112
|
+
app.get('/obs/health', (req, res) => res.json({ connected: Boolean(observationOrgan) }));
|
|
104
113
|
app.get('/me', auth_1.attachIdentity, (req, res) => {
|
|
105
114
|
const identity = req.identity;
|
|
106
115
|
res.json({
|
|
@@ -114,11 +123,18 @@ function createApp(runtimes = new Map()) {
|
|
|
114
123
|
app.post('/chat', auth_1.attachIdentity, async (req, res) => {
|
|
115
124
|
const { id, message, history } = req.body;
|
|
116
125
|
const identity = req.identity;
|
|
126
|
+
// Single-owner companion model: /chat defaults to OWNER identity.
|
|
127
|
+
// Explicit non-owner role in request body or context (e.g. adversarial test suites) is respected.
|
|
128
|
+
const effectiveRole = req.body?.role === 'VIEWER' || req.body?.context?.actor?.authorizationRole === 'viewer'
|
|
129
|
+
? 'VIEWER'
|
|
130
|
+
: (identity?.role === 'OPERATOR' ? 'OPERATOR' : 'OWNER');
|
|
131
|
+
const isOwner = effectiveRole === 'OWNER';
|
|
117
132
|
// Call context mapper at the API boundary
|
|
118
133
|
const mappingResult = (0, context_mapper_1.mapRequestContext)({
|
|
119
134
|
...req.body,
|
|
120
135
|
id: id || req.body.companionId,
|
|
121
|
-
role:
|
|
136
|
+
role: effectiveRole,
|
|
137
|
+
authenticated: isOwner,
|
|
122
138
|
generateCorrelationId: true,
|
|
123
139
|
}, {
|
|
124
140
|
endpointPolicy: 'public',
|
|
@@ -135,13 +151,13 @@ function createApp(runtimes = new Map()) {
|
|
|
135
151
|
if (!runtime)
|
|
136
152
|
return res.status(404).json({ error: "Companion not found" });
|
|
137
153
|
try {
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
154
|
+
const response = await (0, runtime_1.dispatchCompanionChat)(runtime, {
|
|
155
|
+
id: companionId,
|
|
156
|
+
companionId,
|
|
157
|
+
message,
|
|
158
|
+
context: mappingResult.context,
|
|
159
|
+
history,
|
|
160
|
+
});
|
|
145
161
|
res.json(response);
|
|
146
162
|
}
|
|
147
163
|
catch (e) {
|
|
@@ -210,7 +226,26 @@ function createApp(runtimes = new Map()) {
|
|
|
210
226
|
}
|
|
211
227
|
});
|
|
212
228
|
// MEMORY MUTATIONS - PROPOSALS
|
|
213
|
-
app.post('/memory/proposals/update', (0, auth_1.requireRole)(['OWNER', 'OPERATOR']), async (req, res) =>
|
|
229
|
+
app.post('/memory/proposals/update', (0, auth_1.requireRole)(['OWNER', 'OPERATOR']), async (req, res) => {
|
|
230
|
+
const id = req.body.companionId || Array.from(runtimes.keys())[0];
|
|
231
|
+
const runtime = runtimes.get(id);
|
|
232
|
+
if (!runtime)
|
|
233
|
+
return res.status(404).json({ error: "Companion not found" });
|
|
234
|
+
if (!runtime.memory || typeof runtime.memory.updateClaim !== 'function') {
|
|
235
|
+
return res.status(400).json({ error: "Memory organ does not support updating claims" });
|
|
236
|
+
}
|
|
237
|
+
try {
|
|
238
|
+
const claimId = req.body.id || req.body.claimId;
|
|
239
|
+
if (!claimId) {
|
|
240
|
+
return res.status(400).json({ error: "Missing required claim id" });
|
|
241
|
+
}
|
|
242
|
+
const updated = await runtime.memory.updateClaim(claimId, req.body.updates || req.body);
|
|
243
|
+
res.json({ success: true, claim: updated });
|
|
244
|
+
}
|
|
245
|
+
catch (e) {
|
|
246
|
+
res.status(500).json({ error: e.message });
|
|
247
|
+
}
|
|
248
|
+
});
|
|
214
249
|
app.post('/memory/proposals/approve', (0, auth_1.requireRole)(['OWNER', 'OPERATOR']), async (req, res) => {
|
|
215
250
|
const id = req.body.companionId || Array.from(runtimes.keys())[0];
|
|
216
251
|
const runtime = runtimes.get(id);
|
|
@@ -302,135 +337,144 @@ function createApp(runtimes = new Map()) {
|
|
|
302
337
|
res.status(500).json({ error: e.message });
|
|
303
338
|
}
|
|
304
339
|
});
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
authorizationRole: 'operator',
|
|
323
|
-
capabilities: ['chat:public', 'memory:approve'],
|
|
324
|
-
authenticated: true,
|
|
325
|
-
},
|
|
326
|
-
conversation: {
|
|
327
|
-
channel: 'public',
|
|
328
|
-
audienceId: 'audience-public',
|
|
329
|
-
correlationId: req.body?.correlation_id || `corr-${Date.now()}`,
|
|
330
|
-
},
|
|
331
|
-
},
|
|
332
|
-
candidateSpeech: req.body?.speech || 'Mocked staged response for review',
|
|
333
|
-
candidateLanguage: req.body?.language || 'en',
|
|
334
|
-
requiresApproval: req.body?.requiresApproval ?? true,
|
|
340
|
+
const isDevMode = process.env.NODE_ENV !== 'production' || process.env.SIDURI_DEV_MODE === 'true';
|
|
341
|
+
if (isDevMode) {
|
|
342
|
+
app.post('/dev/memory/reset', (0, auth_1.requireRole)(['OWNER']), async (req, res) => {
|
|
343
|
+
const id = req.body.companionId || Array.from(runtimes.keys())[0];
|
|
344
|
+
const runtime = runtimes.get(id);
|
|
345
|
+
if (!runtime)
|
|
346
|
+
return res.status(404).json({ error: "Companion not found" });
|
|
347
|
+
if (!runtime.memory || typeof runtime.memory.resetMemory !== 'function') {
|
|
348
|
+
return res.status(400).json({ error: "Memory organ does not support reset" });
|
|
349
|
+
}
|
|
350
|
+
try {
|
|
351
|
+
await runtime.memory.resetMemory();
|
|
352
|
+
res.json({ reset: true });
|
|
353
|
+
}
|
|
354
|
+
catch (e) {
|
|
355
|
+
res.status(500).json({ error: e.message });
|
|
356
|
+
}
|
|
335
357
|
});
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
358
|
+
app.post('/dev/mock-response', async (req, res) => {
|
|
359
|
+
const companionId = req.body?.companionId || Array.from(runtimes.keys())[0] || 'default';
|
|
360
|
+
const runtime = runtimes.get(companionId);
|
|
361
|
+
if (!runtime)
|
|
362
|
+
return res.status(404).json({ accepted: false, error: 'Companion not found' });
|
|
363
|
+
const staged = runtime.gating.stageResponse({
|
|
364
|
+
requestContext: {
|
|
365
|
+
companionId,
|
|
366
|
+
actor: {
|
|
367
|
+
actorId: 'operator-a',
|
|
368
|
+
sessionId: 'sess-op',
|
|
369
|
+
authorizationRole: 'operator',
|
|
370
|
+
capabilities: ['chat:public', 'memory:approve'],
|
|
371
|
+
authenticated: true,
|
|
372
|
+
},
|
|
373
|
+
conversation: {
|
|
374
|
+
channel: 'public',
|
|
375
|
+
audienceId: 'audience-public',
|
|
376
|
+
correlationId: req.body?.correlation_id || `corr-${Date.now()}`,
|
|
377
|
+
},
|
|
378
|
+
},
|
|
379
|
+
candidateSpeech: req.body?.speech || 'Mocked staged response for review',
|
|
380
|
+
candidateLanguage: req.body?.language || 'en',
|
|
381
|
+
requiresApproval: req.body?.requiresApproval ?? true,
|
|
382
|
+
});
|
|
383
|
+
res.json({
|
|
384
|
+
accepted: true,
|
|
385
|
+
staged: true,
|
|
386
|
+
status: staged.status,
|
|
387
|
+
response_id: staged.responseId,
|
|
388
|
+
correlation_id: staged.correlationId,
|
|
389
|
+
speech: staged.speech,
|
|
390
|
+
});
|
|
343
391
|
});
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
392
|
+
app.post('/dev/approve-response', async (req, res) => {
|
|
393
|
+
const companionId = req.body?.companionId || Array.from(runtimes.keys())[0] || 'default';
|
|
394
|
+
const runtime = runtimes.get(companionId);
|
|
395
|
+
if (!runtime)
|
|
396
|
+
return res.status(404).json({ approved: false, error: 'Companion not found' });
|
|
397
|
+
let responseId = req.body?.responseId;
|
|
398
|
+
let correlationId = req.body?.correlation_id;
|
|
399
|
+
if (!responseId && correlationId) {
|
|
400
|
+
const found = runtime.gating.findStagedPlanByCorrelation(companionId, correlationId);
|
|
401
|
+
if (found) {
|
|
402
|
+
responseId = found.responseId;
|
|
403
|
+
}
|
|
356
404
|
}
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
405
|
+
else if (responseId && !correlationId) {
|
|
406
|
+
const found = runtime.gating.getStagedPlan(responseId);
|
|
407
|
+
if (found) {
|
|
408
|
+
correlationId = found.correlationId;
|
|
409
|
+
}
|
|
362
410
|
}
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
411
|
+
if (!responseId) {
|
|
412
|
+
return res.status(400).json({ approved: false, error: 'UNKNOWN_APPROVAL_ID' });
|
|
413
|
+
}
|
|
414
|
+
const result = runtime.gating.approveResponse({
|
|
415
|
+
responseId,
|
|
416
|
+
companionId,
|
|
417
|
+
correlationId: correlationId || '',
|
|
418
|
+
audienceId: req.body?.audienceId,
|
|
419
|
+
});
|
|
420
|
+
if (!result.success) {
|
|
421
|
+
return res.status(400).json({ approved: false, error: result.reason });
|
|
422
|
+
}
|
|
423
|
+
// Now evaluated as approved
|
|
424
|
+
const evaluation = runtime.gating.evaluateGate(result.plan);
|
|
425
|
+
res.json({
|
|
426
|
+
approved: true,
|
|
427
|
+
status: evaluation.disposition,
|
|
428
|
+
response_id: result.plan.responseId,
|
|
429
|
+
speech: result.plan.speech,
|
|
430
|
+
language: result.plan.language,
|
|
431
|
+
});
|
|
384
432
|
});
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
433
|
+
app.post('/dev/reject-response', async (req, res) => {
|
|
434
|
+
const companionId = req.body?.companionId || Array.from(runtimes.keys())[0] || 'default';
|
|
435
|
+
const runtime = runtimes.get(companionId);
|
|
436
|
+
if (!runtime)
|
|
437
|
+
return res.status(404).json({ rejected: false, error: 'Companion not found' });
|
|
438
|
+
let responseId = req.body?.responseId;
|
|
439
|
+
let correlationId = req.body?.correlation_id;
|
|
440
|
+
if (!responseId && correlationId) {
|
|
441
|
+
const found = runtime.gating.findStagedPlanByCorrelation(companionId, correlationId);
|
|
442
|
+
if (found) {
|
|
443
|
+
responseId = found.responseId;
|
|
444
|
+
}
|
|
397
445
|
}
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
446
|
+
else if (responseId && !correlationId) {
|
|
447
|
+
const found = runtime.gating.getStagedPlan(responseId);
|
|
448
|
+
if (found) {
|
|
449
|
+
correlationId = found.correlationId;
|
|
450
|
+
}
|
|
403
451
|
}
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
452
|
+
if (!responseId) {
|
|
453
|
+
return res.status(400).json({ rejected: false, error: 'UNKNOWN_APPROVAL_ID' });
|
|
454
|
+
}
|
|
455
|
+
const result = runtime.gating.rejectResponse({
|
|
456
|
+
responseId,
|
|
457
|
+
companionId,
|
|
458
|
+
correlationId: correlationId || '',
|
|
459
|
+
reason: req.body?.reason,
|
|
460
|
+
});
|
|
461
|
+
if (!result.success) {
|
|
462
|
+
return res.status(400).json({ rejected: false, error: result.reason });
|
|
463
|
+
}
|
|
464
|
+
res.json({
|
|
465
|
+
rejected: true,
|
|
466
|
+
status: result.plan.status,
|
|
467
|
+
response_id: result.plan.responseId,
|
|
468
|
+
});
|
|
413
469
|
});
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
470
|
+
app.post('/dev/mock-observation', async (req, res) => {
|
|
471
|
+
if (!observationOrgan)
|
|
472
|
+
return res.status(503).json({ accepted: false, reason: 'observation_unavailable' });
|
|
473
|
+
const result = await observationOrgan.ingest(new Uint8Array([115, 121, 110, 116, 104, 101, 116, 105, 99]), 'fixture-observation', 'configured-vision');
|
|
474
|
+
if (!result.observation)
|
|
475
|
+
return res.status(result.duplicate ? 200 : 409).json({ accepted: false, ...result });
|
|
476
|
+
res.status(202).json({ accepted: true, observation: result.observation });
|
|
421
477
|
});
|
|
422
|
-
}
|
|
423
|
-
app.post('/dev/mock-observation', async (req, res) => {
|
|
424
|
-
if (!observationOrgan)
|
|
425
|
-
return res.status(503).json({ accepted: false, reason: 'observation_unavailable' });
|
|
426
|
-
const result = await observationOrgan.ingest(new Uint8Array([115, 121, 110, 116, 104, 101, 116, 105, 99]), 'fixture-observation', 'configured-vision');
|
|
427
|
-
if (!result.observation)
|
|
428
|
-
return res.status(result.duplicate ? 200 : 409).json({ accepted: false, ...result });
|
|
429
|
-
res.status(202).json({ accepted: true, observation: result.observation });
|
|
430
|
-
});
|
|
431
|
-
app.post('/platforms/actions/suggest', (req, res) => res.json({ suggested: true }));
|
|
432
|
-
app.post('/platforms/actions/approve', (req, res) => res.json({ approved: true }));
|
|
433
|
-
app.post('/platforms/actions/reject', (req, res) => res.json({ rejected: true }));
|
|
434
|
-
app.post('/platforms/actions/send', (req, res) => res.json({ sent: true }));
|
|
478
|
+
}
|
|
435
479
|
return { app, runtimes, setObservationOrgan: (org) => { observationOrgan = org; } };
|
|
436
480
|
}
|
package/dist/b0-b6.test.js
CHANGED
|
@@ -79,7 +79,7 @@ describe('T0 B0 & B6 Runtime Proof Suite', () => {
|
|
|
79
79
|
expect(mockKnowledge.search).not.toHaveBeenCalled();
|
|
80
80
|
expect(mockBrain.generatePlan).toHaveBeenCalledWith(expect.objectContaining({
|
|
81
81
|
contextPrompt: '',
|
|
82
|
-
recipient: '
|
|
82
|
+
recipient: 'OWNER',
|
|
83
83
|
}));
|
|
84
84
|
});
|
|
85
85
|
});
|
package/dist/cors.d.ts
ADDED
package/dist/cors.js
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getAllowedOrigins = getAllowedOrigins;
|
|
4
|
+
exports.createCorsOptions = createCorsOptions;
|
|
5
|
+
function getAllowedOrigins() {
|
|
6
|
+
const allowed = new Set([
|
|
7
|
+
'http://localhost:3000',
|
|
8
|
+
'http://127.0.0.1:3000',
|
|
9
|
+
'http://localhost:3001',
|
|
10
|
+
'http://127.0.0.1:3001',
|
|
11
|
+
]);
|
|
12
|
+
if (process.env.PORT) {
|
|
13
|
+
allowed.add(`http://localhost:${process.env.PORT}`);
|
|
14
|
+
allowed.add(`http://127.0.0.1:${process.env.PORT}`);
|
|
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
|
+
return allowed;
|
|
26
|
+
}
|
|
27
|
+
function createCorsOptions() {
|
|
28
|
+
return {
|
|
29
|
+
origin: (origin, callback) => {
|
|
30
|
+
// Allow non-browser requests with no origin header (e.g., native tools, curl)
|
|
31
|
+
if (!origin) {
|
|
32
|
+
return callback(null, true);
|
|
33
|
+
}
|
|
34
|
+
const allowedOrigins = getAllowedOrigins();
|
|
35
|
+
if (allowedOrigins.has(origin)) {
|
|
36
|
+
return callback(null, true);
|
|
37
|
+
}
|
|
38
|
+
return callback(null, false);
|
|
39
|
+
},
|
|
40
|
+
credentials: true,
|
|
41
|
+
};
|
|
42
|
+
}
|
package/dist/index.js
CHANGED
|
@@ -55,7 +55,7 @@ function isDisabled(config) {
|
|
|
55
55
|
function createVoice(config) {
|
|
56
56
|
return isDisabled(config)
|
|
57
57
|
? undefined
|
|
58
|
-
: new voice_1.
|
|
58
|
+
: new voice_1.VoiceAdapter({ provider: config.provider || 'voicevox', baseUrl: process.env.VOICEVOX_URL || 'http://localhost:50021', speakerId: config.speakerId || 1 });
|
|
59
59
|
}
|
|
60
60
|
function createKnowledge(config) {
|
|
61
61
|
if (isDisabled(config))
|
|
@@ -157,8 +157,8 @@ async function bootDefaultCompanion() {
|
|
|
157
157
|
}
|
|
158
158
|
if (process.env.NODE_ENV !== 'test') {
|
|
159
159
|
bootDefaultCompanion().then(() => {
|
|
160
|
-
exports.app.listen(PORT, () => {
|
|
161
|
-
console.log(`Siduri-
|
|
160
|
+
exports.app.listen(Number(PORT), '127.0.0.1', () => {
|
|
161
|
+
console.log(`Siduri-X API running on port ${PORT} (127.0.0.1)`);
|
|
162
162
|
});
|
|
163
163
|
}).catch(e => {
|
|
164
164
|
console.error("Failed to boot default companion:", e);
|
package/dist/index.test.js
CHANGED
|
@@ -29,7 +29,7 @@ describe('API Boundary Context Validation (P2 Route Integration)', () => {
|
|
|
29
29
|
history: [],
|
|
30
30
|
});
|
|
31
31
|
expect(res.status).toBe(200);
|
|
32
|
-
expect(fakeRuntime.handleUserMessage).toHaveBeenCalledWith('Hello neutral world', '
|
|
32
|
+
expect(fakeRuntime.handleUserMessage).toHaveBeenCalledWith('Hello neutral world', 'OWNER', []);
|
|
33
33
|
});
|
|
34
34
|
test('accepts neutral context chat envelope at /chat route', async () => {
|
|
35
35
|
const res = await (0, supertest_1.default)(app)
|