@siduri-x/api 2.0.1 → 2.0.2

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.
@@ -1,4 +1,4 @@
1
1
 
2
- > @siduri-x/api@2.0.1 build /home/zagin/Projects/vxnus-studio/projects/siduri-x/apps/api
2
+ > @siduri-x/api@2.0.2 build /home/zagin/Projects/vxnus-studio/projects/siduri-x/apps/api
3
3
  > tsc
4
4
 
@@ -1,9 +1,13 @@
1
1
 
2
- > @siduri-x/api@2.0.1 test /home/zagin/Projects/vxnus-studio/projects/siduri-x/apps/api
2
+ > @siduri-x/api@2.0.2 test /home/zagin/Projects/vxnus-studio/projects/siduri-x/apps/api
3
3
  > jest --config jest.config.json
4
4
 
5
- PASS src/context-mapper.test.ts (10.14 s)
6
- PASS src/runtime.test.ts (10.545 s)
5
+ PASS src/boot.test.ts (12.448 s)
6
+ PASS src/index.test.ts (12.646 s)
7
+ PASS src/t7-release.test.ts (12.705 s)
8
+ PASS src/knowledge.test.ts (12.82 s)
9
+ PASS src/context-mapper.test.ts
10
+ PASS src/runtime.test.ts
7
11
  ● Console
8
12
 
9
13
  console.error
@@ -20,21 +24,20 @@ PASS src/runtime.test.ts (10.545 s)
20
24
  at ../../packages/core/dist/context-retriever.js:23:25
21
25
  at async Promise.all (index 0)
22
26
  at retrieveRuntimeContext (../../packages/core/dist/context-retriever.js:19:78)
23
- at SiduriRuntime.processPerception (../../packages/core/dist/runtime.js:253:34)
27
+ at contextRetrievalStage (../../packages/core/dist/perception-pipeline.js:66:30)
28
+ at PerceptionPipeline.execute (../../packages/core/dist/perception-pipeline.js:21:34)
24
29
  at Object.<anonymous> (src/runtime.test.ts:74:22)
25
30
 
26
- PASS src/index.test.ts (10.888 s)
27
31
  PASS src/auth.test.ts
28
32
  PASS src/smoke.test.ts
29
- PASS src/t4-gating.test.ts (11.522 s)
30
- PASS src/b0-b6.test.ts
31
- PASS src/t5-experience.test.ts (11.592 s)
32
- PASS src/t7-release.test.ts (11.335 s)
33
33
  PASS src/teach-mode.test.ts
34
- PASS src/t6-security.test.ts (12.22 s)
34
+ PASS src/t5-experience.test.ts
35
+ PASS src/t4-gating.test.ts (13.84 s)
36
+ PASS src/t6-security.test.ts (14.624 s)
37
+ PASS src/b0-b6.test.ts (13.796 s)
35
38
  
36
- Test Suites: 11 passed, 11 total
37
- Tests: 72 passed, 72 total
39
+ Test Suites: 13 passed, 13 total
40
+ Tests: 86 passed, 86 total
38
41
  Snapshots: 0 total
39
- Time: 15.203 s, estimated 16 s
42
+ Time: 17.47 s
40
43
  Ran all test suites.
package/dist/app.d.ts CHANGED
@@ -1,40 +1,8 @@
1
1
  import { Express } from 'express';
2
2
  import { SiduriRuntime } from './runtime';
3
- import { VoiceConfig } from '@siduri-x/voice';
4
- import { EKnowledgeConfig } from '@siduri-x/eknowledge';
5
- import { OpenRouterVisionConfig } from '@siduri-x/vision';
6
- import { Live2DAdapterConfig } from '@siduri-x/body';
7
3
  import { FixtureObservationOrgan } from '@siduri-x/observation';
8
- import { DefaultHandsOrganConfig } from '@siduri-x/hands';
9
- import { EarOrganConfig } from '@siduri-x/ear';
10
- import { DefaultMouthOrganConfig } from '@siduri-x/mouth';
11
- export interface AppBrainConfig {
12
- provider?: 'openrouter' | 'openai-compatible' | string;
13
- model?: string;
14
- apiKey?: string;
15
- apiKeyEnv?: string;
16
- baseUrl?: string;
17
- timeoutMs?: number;
18
- [key: string]: unknown;
19
- }
20
- export interface AppBehaviorConfig {
21
- provider?: 'active_self' | 'none' | string;
22
- preset?: string;
23
- [key: string]: unknown;
24
- }
25
- export interface AppBootCompanionConfig {
26
- name: string;
27
- brain?: AppBrainConfig;
28
- voice?: VoiceConfig;
29
- knowledge?: EKnowledgeConfig;
30
- vision?: OpenRouterVisionConfig;
31
- behavior?: AppBehaviorConfig;
32
- body?: Live2DAdapterConfig;
33
- hands?: DefaultHandsOrganConfig;
34
- ear?: EarOrganConfig;
35
- mouth?: DefaultMouthOrganConfig;
36
- [key: string]: unknown;
37
- }
4
+ import { bootCompanion, AppBrainConfig, AppBehaviorConfig, AppBootCompanionConfig, BootCompanionOptions } from './boot';
5
+ export { AppBrainConfig, AppBehaviorConfig, AppBootCompanionConfig, BootCompanionOptions, bootCompanion, };
38
6
  export interface AppInstance {
39
7
  app: Express;
40
8
  runtimes: Map<string, SiduriRuntime>;
package/dist/app.js CHANGED
@@ -3,123 +3,29 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.bootCompanion = void 0;
6
7
  exports.createApp = createApp;
7
8
  const express_1 = __importDefault(require("express"));
8
9
  const cors_1 = __importDefault(require("cors"));
9
10
  const cors_2 = require("./cors");
10
11
  const runtime_1 = require("./runtime");
11
- const brain_1 = require("@siduri-x/brain");
12
- const memory_1 = require("@siduri-x/memory");
13
- const voice_1 = require("@siduri-x/voice");
14
- const eknowledge_1 = require("@siduri-x/eknowledge");
15
- const vision_1 = require("@siduri-x/vision");
16
12
  const self_1 = require("@siduri-x/self");
17
- const body_1 = require("@siduri-x/body");
18
- const hands_1 = require("@siduri-x/hands");
19
- const ear_1 = require("@siduri-x/ear");
20
- const mouth_1 = require("@siduri-x/mouth");
21
13
  const auth_1 = require("./auth");
22
14
  const context_mapper_1 = require("./context-mapper");
15
+ const boot_1 = require("./boot");
16
+ Object.defineProperty(exports, "bootCompanion", { enumerable: true, get: function () { return boot_1.bootCompanion; } });
23
17
  function createApp(runtimes = new Map()) {
24
18
  const app = (0, express_1.default)();
25
19
  app.use((0, cors_1.default)((0, cors_2.createCorsOptions)()));
26
20
  app.use(express_1.default.json());
27
21
  let observationOrgan;
28
- function createBrain(config) {
29
- const provider = config?.provider || 'openrouter';
30
- const defaultKeyEnv = provider === 'openai-compatible' ? 'OPENAI_COMPATIBLE_API_KEY' : 'OPENROUTER_API_KEY';
31
- const apiKey = config?.apiKey || process.env[config?.apiKeyEnv || defaultKeyEnv] || '';
32
- if (provider === 'openai-compatible') {
33
- return new brain_1.OpenAICompatibleBrain({
34
- apiKey,
35
- model: config?.model || 'local-model',
36
- baseUrl: config?.baseUrl || 'http://127.0.0.1:1234/v1',
37
- });
38
- }
39
- return new brain_1.OpenRouterBrain({ apiKey, model: config?.model || 'gpt-4o-mini' });
40
- }
41
- function isDisabled(config) {
42
- return !config || config.provider === 'none';
43
- }
44
- function createVoice(config) {
45
- return isDisabled(config)
46
- ? undefined
47
- : new voice_1.VoiceAdapter({
48
- provider: config?.provider || 'voicevox',
49
- baseUrl: config?.baseUrl || process.env.VOICEVOX_URL || 'http://localhost:50021',
50
- speakerId: config?.speakerId || 1,
51
- ...config,
52
- });
53
- }
54
- function createKnowledge(config) {
55
- return isDisabled(config) ? undefined : new eknowledge_1.EKnowledgeAdapter(config || {});
56
- }
57
- function createVision(config) {
58
- return isDisabled(config)
59
- ? undefined
60
- : new vision_1.OpenRouterVisionAdapter({
61
- apiKey: config?.apiKey || process.env.OPENROUTER_API_KEY || '',
62
- model: config?.model || 'gpt-4-vision',
63
- ...config,
64
- });
65
- }
66
- function createBehavior(config) {
67
- return isDisabled(config) ? undefined : new self_1.ActiveSelfCompiler();
68
- }
69
- function createBody(config) {
70
- return isDisabled(config)
71
- ? undefined
72
- : new body_1.Live2DAdapter(config);
73
- }
74
- function createHands(config) {
75
- return isDisabled(config)
76
- ? new hands_1.DefaultHandsOrgan()
77
- : new hands_1.DefaultHandsOrgan(config);
78
- }
79
- function createEar(config) {
80
- return isDisabled(config)
81
- ? new ear_1.DefaultEarOrgan()
82
- : new ear_1.DefaultEarOrgan(config);
83
- }
84
- function createMouth(config, voice) {
85
- return isDisabled(config)
86
- ? new mouth_1.DefaultMouthOrgan({ voice })
87
- : new mouth_1.DefaultMouthOrgan({ ...config, voice });
88
- }
89
22
  app.post('/boot', auth_1.requireAuth, async (req, res) => {
90
23
  try {
91
24
  const { id, config } = req.body;
92
25
  if (runtimes.has(id)) {
93
26
  return res.status(400).json({ error: "Already booted" });
94
27
  }
95
- const organs = config?.organs || {};
96
- const brain = createBrain(organs.brain || config?.brain);
97
- const memory = new memory_1.SqliteMemoryStore({ dbPath: process.env.STORAGE_PATH || process.env.SQLITE_DB_PATH || 'siduri.sqlite' });
98
- const selfRepo = new self_1.SqliteSelfRepository({ dbPath: process.env.STORAGE_PATH || process.env.SQLITE_DB_PATH || 'siduri.sqlite' });
99
- const voice = createVoice(organs.voice || config?.voice);
100
- const knowledge = createKnowledge(organs.knowledge || config?.knowledge);
101
- const vision = createVision(organs.vision || config?.vision);
102
- const behavior = createBehavior(organs.behavior || config?.behavior);
103
- const body = createBody(organs.body || config?.body);
104
- const hands = createHands(organs.hands || config?.hands);
105
- const ear = createEar(organs.ear || config?.ear);
106
- const mouth = createMouth(organs.mouth || config?.mouth, voice);
107
- const runtime = new runtime_1.SiduriRuntime(id, config, {
108
- brain,
109
- memory,
110
- voice,
111
- knowledge,
112
- vision,
113
- behavior,
114
- body,
115
- hands,
116
- ear,
117
- mouth,
118
- observation: observationOrgan,
119
- self: selfRepo,
120
- externalKnowledge: knowledge,
121
- });
122
- await runtime.initialize();
28
+ const runtime = await (0, boot_1.bootCompanion)(id, config, { observationOrgan });
123
29
  runtimes.set(id, runtime);
124
30
  res.json({ success: true, id });
125
31
  }
@@ -231,12 +137,18 @@ function createApp(runtimes = new Map()) {
231
137
  app.post('/chat', auth_1.attachIdentity, async (req, res) => {
232
138
  const { id, message, history } = req.body;
233
139
  const identity = req.identity;
234
- // Single-owner companion model: map request context directly
140
+ const local = (0, auth_1.isLocalRequest)(req);
141
+ const hasConfiguredToken = Boolean(process.env.AUTH_TOKEN || process.env.OPERATOR_TOKEN || process.env.OWNER_TOKEN);
142
+ const isLocalDirectOwner = local && !hasConfiguredToken;
143
+ const authenticated = identity?.authenticated || isLocalDirectOwner;
144
+ const serverRole = identity?.authenticated ? identity.role : (isLocalDirectOwner ? 'OWNER' : 'VIEWER');
145
+ // Single-owner companion model: map request context directly with server identity enforcement
235
146
  const mappingResult = (0, context_mapper_1.mapRequestContext)({
236
147
  ...req.body,
237
148
  id: id || req.body.companionId,
238
- authenticated: identity?.authenticated ?? true,
239
- source: identity?.source ?? 'local',
149
+ authenticated,
150
+ serverRole,
151
+ source: identity?.source ?? (local ? 'local' : 'external'),
240
152
  generateCorrelationId: true,
241
153
  });
242
154
  if (!mappingResult.accepted) {
@@ -268,11 +180,17 @@ function createApp(runtimes = new Map()) {
268
180
  app.post('/chat/stream', auth_1.attachIdentity, async (req, res) => {
269
181
  const { id, message, history } = req.body;
270
182
  const identity = req.identity;
183
+ const local = (0, auth_1.isLocalRequest)(req);
184
+ const hasConfiguredToken = Boolean(process.env.AUTH_TOKEN || process.env.OPERATOR_TOKEN || process.env.OWNER_TOKEN);
185
+ const isLocalDirectOwner = local && !hasConfiguredToken;
186
+ const authenticated = identity?.authenticated || isLocalDirectOwner;
187
+ const serverRole = identity?.authenticated ? identity.role : (isLocalDirectOwner ? 'OWNER' : 'VIEWER');
271
188
  const mappingResult = (0, context_mapper_1.mapRequestContext)({
272
189
  ...req.body,
273
190
  id: id || req.body.companionId,
274
- authenticated: identity?.authenticated ?? true,
275
- source: identity?.source ?? 'local',
191
+ authenticated,
192
+ serverRole,
193
+ source: identity?.source ?? (local ? 'local' : 'external'),
276
194
  generateCorrelationId: true,
277
195
  });
278
196
  if (!mappingResult.accepted) {
@@ -292,8 +210,8 @@ function createApp(runtimes = new Map()) {
292
210
  const abortController = new AbortController();
293
211
  const onClose = () => {
294
212
  abortController.abort('client_disconnect');
295
- if (typeof runtime.interruptMouth === 'function') {
296
- runtime.interruptMouth('client_disconnect');
213
+ if (runtime.mouth && typeof runtime.mouth.interrupt === 'function') {
214
+ runtime.mouth.interrupt('client_disconnect');
297
215
  }
298
216
  };
299
217
  req.on('close', onClose);
@@ -360,11 +278,15 @@ function createApp(runtimes = new Map()) {
360
278
  const runtime = companionId ? runtimes.get(companionId) : undefined;
361
279
  const reason = req.body?.reason || 'user_barge_in';
362
280
  if (runtime) {
363
- runtime.interruptMouth(reason);
281
+ if (runtime.mouth && typeof runtime.mouth.interrupt === 'function') {
282
+ runtime.mouth.interrupt(reason);
283
+ }
364
284
  return res.json({ success: true, interrupted: true, companionId, reason });
365
285
  }
366
286
  for (const r of runtimes.values()) {
367
- r.interruptMouth(reason);
287
+ if (r.mouth && typeof r.mouth.interrupt === 'function') {
288
+ r.mouth.interrupt(reason);
289
+ }
368
290
  }
369
291
  return res.json({ success: true, interrupted: true, reason });
370
292
  });
@@ -373,11 +295,15 @@ function createApp(runtimes = new Map()) {
373
295
  const runtime = companionId ? runtimes.get(companionId) : undefined;
374
296
  const reason = req.body?.reason || 'user_barge_in';
375
297
  if (runtime) {
376
- runtime.interruptMouth(reason);
298
+ if (runtime.mouth && typeof runtime.mouth.interrupt === 'function') {
299
+ runtime.mouth.interrupt(reason);
300
+ }
377
301
  return res.json({ success: true, interrupted: true, companionId, reason });
378
302
  }
379
303
  for (const r of runtimes.values()) {
380
- r.interruptMouth(reason);
304
+ if (r.mouth && typeof r.mouth.interrupt === 'function') {
305
+ r.mouth.interrupt(reason);
306
+ }
381
307
  }
382
308
  return res.json({ success: true, interrupted: true, reason });
383
309
  });
@@ -390,7 +316,7 @@ function createApp(runtimes = new Map()) {
390
316
  if (!runtime.memory)
391
317
  return res.json({ proposals: [] });
392
318
  try {
393
- const proposals = await runtime.getPendingClaims();
319
+ const proposals = await runtime.memory.getPendingClaims();
394
320
  res.json({ proposals });
395
321
  }
396
322
  catch (e) {
@@ -405,7 +331,7 @@ function createApp(runtimes = new Map()) {
405
331
  if (!runtime.memory)
406
332
  return res.json({ items: [] });
407
333
  try {
408
- const items = await runtime.getClaims();
334
+ const items = await runtime.memory.getClaims();
409
335
  res.json({ items });
410
336
  }
411
337
  catch (e) {
@@ -420,7 +346,7 @@ function createApp(runtimes = new Map()) {
420
346
  if (!runtime.memory)
421
347
  return res.json({ claims: [] });
422
348
  try {
423
- const claims = await runtime.getClaims();
349
+ const claims = await runtime.memory.getClaims();
424
350
  res.json({ claims });
425
351
  }
426
352
  catch (e) {
@@ -435,13 +361,101 @@ function createApp(runtimes = new Map()) {
435
361
  if (!runtime.memory)
436
362
  return res.json({ directives: [] });
437
363
  try {
438
- const directives = await runtime.getDirectives();
364
+ const directives = await runtime.memory.getDirectives();
439
365
  res.json({ directives });
440
366
  }
441
367
  catch (e) {
442
368
  res.status(500).json({ error: e.message });
443
369
  }
444
370
  });
371
+ // KNOWLEDGE / LIFE DB GETTERS
372
+ app.get('/knowledge/life', auth_1.requireAuth, async (req, res) => {
373
+ const id = req.query.id || Array.from(runtimes.keys())[0];
374
+ const runtime = runtimes.get(id);
375
+ if (!runtime)
376
+ return res.status(404).json({ error: "Companion not found" });
377
+ const query = req.query.q || '';
378
+ if (!runtime.knowledge || typeof runtime.knowledge.queryLifeContext !== 'function') {
379
+ return res.json({ matchedInventory: [], recentFinances: [], upcomingSchedule: [], preferences: [], formattedContext: '' });
380
+ }
381
+ try {
382
+ const result = await runtime.knowledge.queryLifeContext(id, query);
383
+ res.json(result);
384
+ }
385
+ catch (e) {
386
+ res.status(500).json({ error: e.message });
387
+ }
388
+ });
389
+ app.get('/knowledge/inventory', auth_1.requireAuth, async (req, res) => {
390
+ const id = req.query.id || Array.from(runtimes.keys())[0];
391
+ const runtime = runtimes.get(id);
392
+ if (!runtime)
393
+ return res.status(404).json({ error: "Companion not found" });
394
+ const domain = req.query.domain;
395
+ if (!runtime.knowledge || !runtime.knowledge.inventory) {
396
+ return res.json({ items: [] });
397
+ }
398
+ try {
399
+ const items = await runtime.knowledge.inventory.getItems(id, domain);
400
+ res.json({ items });
401
+ }
402
+ catch (e) {
403
+ res.status(500).json({ error: e.message });
404
+ }
405
+ });
406
+ app.get('/knowledge/finance', auth_1.requireAuth, async (req, res) => {
407
+ const id = req.query.id || Array.from(runtimes.keys())[0];
408
+ const runtime = runtimes.get(id);
409
+ if (!runtime)
410
+ return res.status(404).json({ error: "Companion not found" });
411
+ if (!runtime.knowledge || !runtime.knowledge.finance) {
412
+ return res.json({ summary: null, entries: [] });
413
+ }
414
+ try {
415
+ const limit = Number(req.query.limit || 20);
416
+ const [summary, entries] = await Promise.all([
417
+ runtime.knowledge.finance.getSummary(id),
418
+ runtime.knowledge.finance.getEntries(id, limit),
419
+ ]);
420
+ res.json({ summary, entries });
421
+ }
422
+ catch (e) {
423
+ res.status(500).json({ error: e.message });
424
+ }
425
+ });
426
+ app.get('/knowledge/schedule', auth_1.requireAuth, async (req, res) => {
427
+ const id = req.query.id || Array.from(runtimes.keys())[0];
428
+ const runtime = runtimes.get(id);
429
+ if (!runtime)
430
+ return res.status(404).json({ error: "Companion not found" });
431
+ if (!runtime.knowledge || !runtime.knowledge.schedule) {
432
+ return res.json({ items: [] });
433
+ }
434
+ try {
435
+ const items = await runtime.knowledge.schedule.getUpcoming(id);
436
+ res.json({ items });
437
+ }
438
+ catch (e) {
439
+ res.status(500).json({ error: e.message });
440
+ }
441
+ });
442
+ app.get('/knowledge/preferences', auth_1.requireAuth, async (req, res) => {
443
+ const id = req.query.id || Array.from(runtimes.keys())[0];
444
+ const runtime = runtimes.get(id);
445
+ if (!runtime)
446
+ return res.status(404).json({ error: "Companion not found" });
447
+ const category = req.query.category;
448
+ if (!runtime.knowledge || !runtime.knowledge.preferences) {
449
+ return res.json({ preferences: [] });
450
+ }
451
+ try {
452
+ const preferences = await runtime.knowledge.preferences.getPreferences(id, category);
453
+ res.json({ preferences });
454
+ }
455
+ catch (e) {
456
+ res.status(500).json({ error: e.message });
457
+ }
458
+ });
445
459
  // MEMORY MUTATIONS - PROPOSALS
446
460
  app.post('/memory/proposals/update', auth_1.requireAuth, async (req, res) => {
447
461
  const id = req.body.companionId || Array.from(runtimes.keys())[0];
@@ -456,7 +470,7 @@ function createApp(runtimes = new Map()) {
456
470
  if (!claimId) {
457
471
  return res.status(400).json({ error: "Missing required claim id" });
458
472
  }
459
- const updated = await runtime.updateClaim(claimId, req.body.updates || req.body);
473
+ const updated = await runtime.memory.updateClaim(claimId, req.body.updates || req.body);
460
474
  res.json({ success: true, claim: updated });
461
475
  }
462
476
  catch (e) {
@@ -471,7 +485,7 @@ function createApp(runtimes = new Map()) {
471
485
  if (!runtime.memory)
472
486
  return res.status(400).json({ error: "Memory organ not configured" });
473
487
  try {
474
- await runtime.approveClaim(req.body.id);
488
+ await runtime.memory.approveClaim(req.body.id);
475
489
  res.json({ approved: true });
476
490
  }
477
491
  catch (e) {
@@ -486,7 +500,7 @@ function createApp(runtimes = new Map()) {
486
500
  if (!runtime.memory)
487
501
  return res.status(400).json({ error: "Memory organ not configured" });
488
502
  try {
489
- await runtime.rejectClaim(req.body.id);
503
+ await runtime.memory.rejectClaim(req.body.id);
490
504
  res.json({ rejected: true });
491
505
  }
492
506
  catch (e) {
@@ -502,7 +516,7 @@ function createApp(runtimes = new Map()) {
502
516
  if (!runtime.memory)
503
517
  return res.status(400).json({ error: "Memory organ not configured" });
504
518
  try {
505
- await runtime.approveDirective(req.body.id);
519
+ await runtime.memory.approveDirective(req.body.id);
506
520
  res.json({ approved: true });
507
521
  }
508
522
  catch (e) {
@@ -517,7 +531,7 @@ function createApp(runtimes = new Map()) {
517
531
  if (!runtime.memory)
518
532
  return res.status(400).json({ error: "Memory organ not configured" });
519
533
  try {
520
- await runtime.rejectDirective(req.body.id);
534
+ await runtime.memory.rejectDirective(req.body.id);
521
535
  res.json({ rejected: true });
522
536
  }
523
537
  catch (e) {
@@ -532,7 +546,7 @@ function createApp(runtimes = new Map()) {
532
546
  if (!runtime.memory)
533
547
  return res.status(400).json({ error: "Memory organ not configured" });
534
548
  try {
535
- await runtime.revokeDirective(req.body.id);
549
+ await runtime.memory.revokeDirective(req.body.id);
536
550
  res.json({ revoked: true });
537
551
  }
538
552
  catch (e) {
@@ -547,7 +561,7 @@ function createApp(runtimes = new Map()) {
547
561
  if (!runtime.memory)
548
562
  return res.status(400).json({ error: "Memory organ not configured" });
549
563
  try {
550
- await runtime.disableDirective(req.body.id);
564
+ await runtime.memory.disableDirective(req.body.id);
551
565
  res.json({ disabled: true });
552
566
  }
553
567
  catch (e) {
@@ -565,7 +579,7 @@ function createApp(runtimes = new Map()) {
565
579
  return res.status(400).json({ error: "Memory organ does not support reset" });
566
580
  }
567
581
  try {
568
- await runtime.resetMemory();
582
+ await runtime.memory.resetMemory();
569
583
  res.json({ reset: true });
570
584
  }
571
585
  catch (e) {
@@ -577,7 +591,7 @@ function createApp(runtimes = new Map()) {
577
591
  const runtime = runtimes.get(companionId);
578
592
  if (!runtime)
579
593
  return res.status(404).json({ accepted: false, error: 'Companion not found' });
580
- const staged = runtime.stageResponse({
594
+ const staged = runtime.gating.stageResponse({
581
595
  requestContext: {
582
596
  companionId,
583
597
  actor: {
@@ -611,13 +625,13 @@ function createApp(runtimes = new Map()) {
611
625
  let responseId = req.body?.responseId;
612
626
  let correlationId = req.body?.correlation_id;
613
627
  if (!responseId && correlationId) {
614
- const found = runtime.findStagedPlanByCorrelation(companionId, correlationId);
628
+ const found = runtime.gating.findStagedPlanByCorrelation(companionId, correlationId);
615
629
  if (found) {
616
630
  responseId = found.responseId;
617
631
  }
618
632
  }
619
633
  else if (responseId && !correlationId) {
620
- const found = runtime.getStagedPlan(responseId);
634
+ const found = runtime.gating.getStagedPlan(responseId);
621
635
  if (found) {
622
636
  correlationId = found.correlationId;
623
637
  }
@@ -625,7 +639,7 @@ function createApp(runtimes = new Map()) {
625
639
  if (!responseId) {
626
640
  return res.status(400).json({ approved: false, error: 'UNKNOWN_APPROVAL_ID' });
627
641
  }
628
- const result = runtime.approveResponse({
642
+ const result = runtime.gating.approveResponse({
629
643
  responseId,
630
644
  companionId,
631
645
  correlationId: correlationId || '',
@@ -634,7 +648,7 @@ function createApp(runtimes = new Map()) {
634
648
  return res.status(400).json({ approved: false, error: result.reason });
635
649
  }
636
650
  // Now evaluated as approved
637
- const evaluation = runtime.evaluateGate(result.plan);
651
+ const evaluation = runtime.gating.evaluateGate(result.plan);
638
652
  res.json({
639
653
  approved: true,
640
654
  status: evaluation.disposition,
@@ -651,13 +665,13 @@ function createApp(runtimes = new Map()) {
651
665
  let responseId = req.body?.responseId;
652
666
  let correlationId = req.body?.correlation_id;
653
667
  if (!responseId && correlationId) {
654
- const found = runtime.findStagedPlanByCorrelation(companionId, correlationId);
668
+ const found = runtime.gating.findStagedPlanByCorrelation(companionId, correlationId);
655
669
  if (found) {
656
670
  responseId = found.responseId;
657
671
  }
658
672
  }
659
673
  else if (responseId && !correlationId) {
660
- const found = runtime.getStagedPlan(responseId);
674
+ const found = runtime.gating.getStagedPlan(responseId);
661
675
  if (found) {
662
676
  correlationId = found.correlationId;
663
677
  }
@@ -665,7 +679,7 @@ function createApp(runtimes = new Map()) {
665
679
  if (!responseId) {
666
680
  return res.status(400).json({ rejected: false, error: 'UNKNOWN_APPROVAL_ID' });
667
681
  }
668
- const result = runtime.rejectResponse({
682
+ const result = runtime.gating.rejectResponse({
669
683
  responseId,
670
684
  companionId,
671
685
  correlationId: correlationId || '',
package/dist/boot.d.ts ADDED
@@ -0,0 +1,92 @@
1
+ import { OpenAICompatibleBrain } from '@siduri-x/brain';
2
+ import { SqliteMemoryStore } from '@siduri-x/memory';
3
+ import { VoiceAdapter, VoiceConfig } from '@siduri-x/voice';
4
+ import { UnifiedKnowledgeOrgan, UnifiedKnowledgeConfig } from '@siduri-x/knowledge';
5
+ import { OpenRouterVisionAdapter, OpenRouterVisionConfig } from '@siduri-x/vision';
6
+ import { ActiveSelfCompiler, SqliteSelfRepository } from '@siduri-x/self';
7
+ import { Live2DAdapterConfig } from '@siduri-x/body';
8
+ import { FixtureObservationOrgan } from '@siduri-x/observation';
9
+ import { DefaultHandsOrgan, DefaultHandsOrganConfig } from '@siduri-x/hands';
10
+ import { DefaultEarOrgan, EarOrganConfig } from '@siduri-x/ear';
11
+ import { DefaultMouthOrgan, DefaultMouthOrganConfig } from '@siduri-x/mouth';
12
+ import { SiduriRuntime } from './runtime';
13
+ export interface AppBrainConfig {
14
+ provider?: 'openrouter' | 'openai-compatible' | string;
15
+ model?: string;
16
+ apiKey?: string;
17
+ apiKeyEnv?: string;
18
+ baseUrl?: string;
19
+ timeoutMs?: number;
20
+ [key: string]: unknown;
21
+ }
22
+ export interface AppBehaviorConfig {
23
+ provider?: 'active_self' | 'none' | string;
24
+ preset?: string;
25
+ [key: string]: unknown;
26
+ }
27
+ export interface AppBootCompanionConfig {
28
+ name: string;
29
+ id?: string;
30
+ brain?: AppBrainConfig;
31
+ voice?: VoiceConfig;
32
+ memory?: {
33
+ provider?: string;
34
+ connectionString?: string;
35
+ maxConnections?: number;
36
+ dbPath?: string;
37
+ [key: string]: unknown;
38
+ };
39
+ knowledge?: UnifiedKnowledgeConfig;
40
+ vision?: OpenRouterVisionConfig;
41
+ behavior?: AppBehaviorConfig;
42
+ body?: Live2DAdapterConfig;
43
+ hands?: DefaultHandsOrganConfig;
44
+ ear?: EarOrganConfig;
45
+ mouth?: DefaultMouthOrganConfig;
46
+ self?: {
47
+ dbPath?: string;
48
+ [key: string]: unknown;
49
+ };
50
+ organs?: Record<string, any>;
51
+ [key: string]: unknown;
52
+ }
53
+ export interface BootCompanionOptions {
54
+ observationOrgan?: FixtureObservationOrgan;
55
+ }
56
+ export declare function isDisabled(config?: {
57
+ provider?: string;
58
+ }): boolean;
59
+ export declare function createBrain(config?: AppBrainConfig): OpenAICompatibleBrain;
60
+ export declare function createVoice(config?: VoiceConfig): VoiceAdapter | undefined;
61
+ export declare function createKnowledge(config?: UnifiedKnowledgeConfig): UnifiedKnowledgeOrgan | undefined;
62
+ export declare function createVision(config?: OpenRouterVisionConfig & {
63
+ provider?: string;
64
+ }): OpenRouterVisionAdapter | undefined;
65
+ export declare function createBehavior(config?: AppBehaviorConfig): ActiveSelfCompiler | undefined;
66
+ export declare function createBody(config?: Live2DAdapterConfig & {
67
+ provider?: string;
68
+ }): import("@siduri-x/body").NeutralBodyOrgan | undefined;
69
+ export declare function createHands(config?: DefaultHandsOrganConfig & {
70
+ provider?: string;
71
+ }): DefaultHandsOrgan;
72
+ export declare function createEar(config?: EarOrganConfig & {
73
+ provider?: string;
74
+ }): DefaultEarOrgan;
75
+ export declare function createMouth(config?: DefaultMouthOrganConfig & {
76
+ provider?: string;
77
+ }, voice?: any): DefaultMouthOrgan;
78
+ export declare function createMemory(config?: {
79
+ provider?: string;
80
+ connectionString?: string;
81
+ maxConnections?: number;
82
+ dbPath?: string;
83
+ }): SqliteMemoryStore | undefined;
84
+ export declare function createSelf(config?: {
85
+ dbPath?: string;
86
+ }): SqliteSelfRepository;
87
+ export declare function createObservation(vision?: any): FixtureObservationOrgan;
88
+ /**
89
+ * Canonical companion bootstrapper.
90
+ * Wires all 10 organs, runs memory migrations, and initializes the SiduriRuntime.
91
+ */
92
+ export declare function bootCompanion(id: string, config: AppBootCompanionConfig, options?: BootCompanionOptions): Promise<SiduriRuntime>;