@vxnus/siduri 0.1.6 → 0.1.8

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.
Files changed (98) hide show
  1. package/package.json +1 -1
  2. package/dist/builtin-manifests.d.ts +0 -2
  3. package/dist/builtin-manifests.js +0 -464
  4. package/dist/clean-machine-e2e.test.d.ts +0 -1
  5. package/dist/clean-machine-e2e.test.js +0 -230
  6. package/dist/configurators/behavior.d.ts +0 -2
  7. package/dist/configurators/behavior.js +0 -36
  8. package/dist/configurators/body.d.ts +0 -2
  9. package/dist/configurators/body.js +0 -60
  10. package/dist/configurators/brain.d.ts +0 -6
  11. package/dist/configurators/brain.js +0 -80
  12. package/dist/configurators/ear.d.ts +0 -2
  13. package/dist/configurators/ear.js +0 -28
  14. package/dist/configurators/hands.d.ts +0 -2
  15. package/dist/configurators/hands.js +0 -27
  16. package/dist/configurators/index.d.ts +0 -23
  17. package/dist/configurators/index.js +0 -74
  18. package/dist/configurators/knowledge.d.ts +0 -6
  19. package/dist/configurators/knowledge.js +0 -100
  20. package/dist/configurators/memory.d.ts +0 -2
  21. package/dist/configurators/memory.js +0 -44
  22. package/dist/configurators/observation.d.ts +0 -2
  23. package/dist/configurators/observation.js +0 -12
  24. package/dist/configurators/types.d.ts +0 -12
  25. package/dist/configurators/types.js +0 -2
  26. package/dist/configurators/vision.d.ts +0 -2
  27. package/dist/configurators/vision.js +0 -39
  28. package/dist/configurators/voice.d.ts +0 -2
  29. package/dist/configurators/voice.js +0 -363
  30. package/dist/configurators.test.d.ts +0 -1
  31. package/dist/configurators.test.js +0 -299
  32. package/dist/db.d.ts +0 -25
  33. package/dist/db.js +0 -152
  34. package/dist/discovery.d.ts +0 -13
  35. package/dist/discovery.js +0 -87
  36. package/dist/discovery.test.d.ts +0 -1
  37. package/dist/discovery.test.js +0 -67
  38. package/dist/doctor-db.test.d.ts +0 -1
  39. package/dist/doctor-db.test.js +0 -141
  40. package/dist/doctor.d.ts +0 -19
  41. package/dist/doctor.js +0 -225
  42. package/dist/generator.d.ts +0 -21
  43. package/dist/generator.js +0 -542
  44. package/dist/generator.test.d.ts +0 -1
  45. package/dist/generator.test.js +0 -197
  46. package/dist/index.d.ts +0 -20
  47. package/dist/index.js +0 -401
  48. package/dist/manifest.d.ts +0 -33
  49. package/dist/manifest.js +0 -40
  50. package/dist/providers/knowledge-hub.d.ts +0 -37
  51. package/dist/providers/knowledge-hub.js +0 -141
  52. package/dist/providers/openrouter.d.ts +0 -32
  53. package/dist/providers/openrouter.js +0 -201
  54. package/dist/release-check.d.ts +0 -9
  55. package/dist/release-check.js +0 -131
  56. package/dist/runtime-parity.test.d.ts +0 -1
  57. package/dist/runtime-parity.test.js +0 -140
  58. package/dist/web-dist/404/index.html +0 -1
  59. package/dist/web-dist/404.html +0 -1
  60. package/dist/web-dist/__next.__PAGE__.txt +0 -34
  61. package/dist/web-dist/__next._full.txt +0 -31
  62. package/dist/web-dist/__next._tree.txt +0 -3
  63. package/dist/web-dist/_next/static/D38KTbM_PIeZqLpHvixAH/_buildManifest.js +0 -11
  64. package/dist/web-dist/_next/static/D38KTbM_PIeZqLpHvixAH/_clientMiddlewareManifest.js +0 -1
  65. package/dist/web-dist/_next/static/D38KTbM_PIeZqLpHvixAH/_ssgManifest.js +0 -1
  66. package/dist/web-dist/_next/static/chunks/0cz1d0mv5g_q7.js +0 -1
  67. package/dist/web-dist/_next/static/chunks/0uwih7sydv413.js +0 -1
  68. package/dist/web-dist/_next/static/chunks/10rmct1ax-opq.js +0 -1
  69. package/dist/web-dist/_next/static/chunks/1_yae15ffa5f6.js +0 -1
  70. package/dist/web-dist/_next/static/chunks/1eusi7dzngpy3.js +0 -30
  71. package/dist/web-dist/_next/static/chunks/2kcqevsmv6kh2.js +0 -31
  72. package/dist/web-dist/_next/static/chunks/2s3d1bfr0l4b0.js +0 -1
  73. package/dist/web-dist/_next/static/chunks/2vh8hinyh9xfg.css +0 -1
  74. package/dist/web-dist/_next/static/chunks/32z87id9k6i2z.js +0 -22
  75. package/dist/web-dist/_next/static/chunks/3bx2gs3idjmo1.js +0 -1
  76. package/dist/web-dist/_next/static/chunks/turbopack-3eipe4c-imn5l.js +0 -1
  77. package/dist/web-dist/_next/static/media/favicon.2vob68tjqpejf.ico +0 -0
  78. package/dist/web-dist/_not-found/__next._full.txt +0 -17
  79. package/dist/web-dist/_not-found/__next._not-found.__PAGE__.txt +0 -23
  80. package/dist/web-dist/_not-found/__next._tree.txt +0 -3
  81. package/dist/web-dist/_not-found/index.html +0 -1
  82. package/dist/web-dist/_not-found/index.txt +0 -17
  83. package/dist/web-dist/chat/__next._full.txt +0 -18
  84. package/dist/web-dist/chat/__next._tree.txt +0 -3
  85. package/dist/web-dist/chat/__next.chat.__PAGE__.txt +0 -24
  86. package/dist/web-dist/chat/index.html +0 -1
  87. package/dist/web-dist/chat/index.txt +0 -18
  88. package/dist/web-dist/favicon.ico +0 -0
  89. package/dist/web-dist/index.html +0 -1
  90. package/dist/web-dist/index.txt +0 -31
  91. package/dist/web-dist/live2d/live2dcubismcore.min.js +0 -9
  92. package/dist/web-dist/operator/__next._full.txt +0 -18
  93. package/dist/web-dist/operator/__next._tree.txt +0 -3
  94. package/dist/web-dist/operator/__next.operator.__PAGE__.txt +0 -24
  95. package/dist/web-dist/operator/index.html +0 -1
  96. package/dist/web-dist/operator/index.txt +0 -18
  97. package/dist/web-template.d.ts +0 -2
  98. package/dist/web-template.js +0 -556
package/dist/generator.js DELETED
@@ -1,542 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.generateInstanceFiles = generateInstanceFiles;
4
- const web_template_1 = require("./web-template");
5
- function getDefaultConfigForManifest(manifest) {
6
- const schema = manifest.configSchema || {};
7
- const props = schema.properties || {};
8
- const config = {};
9
- for (const [key, val] of Object.entries(props)) {
10
- if (val.default !== undefined) {
11
- config[key] = val.default;
12
- }
13
- else if (val.enum && val.enum.length > 0) {
14
- config[key] = val.enum[0];
15
- }
16
- else if (val.type === 'string') {
17
- config[key] = '';
18
- }
19
- else if (val.type === 'number') {
20
- config[key] = 0;
21
- }
22
- else if (val.type === 'boolean') {
23
- config[key] = false;
24
- }
25
- else if (val.type === 'array') {
26
- config[key] = [];
27
- }
28
- else if (val.type === 'object') {
29
- config[key] = {};
30
- }
31
- }
32
- // Provide sensible defaults for known common keys if missing
33
- if (manifest.organType === 'brain') {
34
- config.provider = config.provider || 'openrouter';
35
- config.model = config.model || 'anthropic/claude-3.5-sonnet';
36
- config.apiKeyEnv = 'OPENROUTER_API_KEY';
37
- }
38
- else if (manifest.organType === 'memory') {
39
- config.provider = config.provider || 'postgres';
40
- }
41
- else if (manifest.organType === 'voice') {
42
- config.provider = config.provider || 'voicevox';
43
- config.speakerId = config.speakerId || 1;
44
- config.baseUrl = config.baseUrl || 'http://localhost:50021';
45
- }
46
- else if (manifest.organType === 'body') {
47
- config.provider = config.provider || 'live2d';
48
- config.initialExpression = config.initialExpression || 'neutral';
49
- config.modelPath = config.modelPath || './assets/body/default/model.model3.json';
50
- config.modelUrl = config.modelUrl || '/assets/body/default/model.model3.json';
51
- }
52
- else if (manifest.organType === 'hands') {
53
- config.defaultTimeoutMs = config.defaultTimeoutMs || 10000;
54
- config.providers = config.providers || [];
55
- }
56
- else if (manifest.organType === 'knowledge') {
57
- config.provider = config.provider || 'none';
58
- }
59
- else if (manifest.organType === 'behavior') {
60
- config.provider = config.provider || 'active_self';
61
- }
62
- else if (manifest.organType === 'vision') {
63
- config.provider = config.provider || 'openrouter';
64
- config.model = config.model || 'gpt-4-vision';
65
- }
66
- return config;
67
- }
68
- function generateInstanceFiles(options) {
69
- const instanceName = options.name || 'my-siduri';
70
- const instanceId = options.id || 'default';
71
- const coreVersion = options.coreVersion || '^1.0.3';
72
- const manifests = options.selectedManifests;
73
- const hasMemory = manifests.some((m) => m.organType === 'memory');
74
- const hasVoice = manifests.some((m) => m.organType === 'voice');
75
- const hasBody = manifests.some((m) => m.organType === 'body');
76
- const voiceConfig = options.organConfigs?.voice || options.organConfigs?.['@siduri-x/voice'];
77
- const isVoicevox = hasVoice && (!voiceConfig || voiceConfig.provider === 'voicevox');
78
- const memoryConfig = options.organConfigs?.memory || options.organConfigs?.['@siduri-x/memory'];
79
- const isPostgresLocal = hasMemory && (!memoryConfig || memoryConfig.deployment === 'local' || memoryConfig.provider === 'postgres');
80
- // 1. Optional docker-compose.yml
81
- let dockerComposeYaml;
82
- const dockerServices = [];
83
- const dockerVolumes = [];
84
- if (hasMemory && isPostgresLocal) {
85
- dockerServices.push([
86
- ' db:',
87
- ' image: postgres:15',
88
- ' environment:',
89
- ' POSTGRES_USER: postgres',
90
- ' POSTGRES_PASSWORD: password',
91
- ' POSTGRES_DB: siduri',
92
- ' ports:',
93
- ' - "5432:5432"',
94
- ' volumes:',
95
- ' - postgres_data:/var/lib/postgresql/data',
96
- ' healthcheck:',
97
- ' test: ["CMD-SHELL", "pg_isready -U postgres"]',
98
- ' interval: 2s',
99
- ' timeout: 5s',
100
- ' retries: 5',
101
- ].join('\n'));
102
- dockerVolumes.push(' postgres_data:');
103
- }
104
- if (hasVoice && voiceConfig?.rvc?.enabled) {
105
- dockerServices.push([
106
- ' rvc:',
107
- ' image: ghcr.io/vxnus-studio/rvc-headless:latest',
108
- ' ports:',
109
- ' - "50055:50055"',
110
- ' volumes:',
111
- ' - ./assets/voice:/app/models',
112
- ' environment:',
113
- ' - RVC_MODELS_DIR=/app/models',
114
- ].join('\n'));
115
- }
116
- if (dockerServices.length > 0) {
117
- const composeLines = [
118
- 'version: "3.8"',
119
- '',
120
- 'services:',
121
- ...dockerServices,
122
- ];
123
- if (dockerVolumes.length > 0) {
124
- composeLines.push('', 'volumes:', ...dockerVolumes);
125
- }
126
- composeLines.push('');
127
- dockerComposeYaml = composeLines.join('\n');
128
- }
129
- // 2. package.json
130
- const dependencies = {
131
- '@siduri-x/core': coreVersion,
132
- };
133
- for (const m of manifests) {
134
- dependencies[m.name] = `^${m.version || '1.0.1'}`;
135
- }
136
- const scripts = {
137
- start: 'node src/index.js',
138
- dev: 'node --watch src/index.js',
139
- doctor: 'siduri doctor',
140
- db: 'siduri db',
141
- };
142
- if (dockerComposeYaml) {
143
- scripts['services:up'] = 'docker compose up -d';
144
- scripts['services:down'] = 'docker compose down';
145
- scripts['services:logs'] = 'docker compose logs -f';
146
- }
147
- const packageJsonObj = {
148
- name: instanceName.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '') || 'my-siduri',
149
- private: true,
150
- type: 'module',
151
- scripts,
152
- dependencies,
153
- };
154
- const packageJson = JSON.stringify(packageJsonObj, null, 2) + '\n';
155
- // 3. siduri.config.json
156
- const organsConfig = {};
157
- for (const m of manifests) {
158
- const customConfig = options.organConfigs?.[m.configKey] || options.organConfigs?.[m.organType];
159
- organsConfig[m.configKey] = customConfig || getDefaultConfigForManifest(m);
160
- }
161
- const configObj = {
162
- $schema: './siduri.schema.json',
163
- id: instanceId,
164
- name: instanceName,
165
- organs: organsConfig,
166
- };
167
- const siduriConfigJson = JSON.stringify(configObj, null, 2) + '\n';
168
- // 4. siduri.schema.json
169
- const organPropertiesSchema = {};
170
- for (const m of manifests) {
171
- organPropertiesSchema[m.configKey] = m.configSchema || { type: 'object' };
172
- }
173
- const schemaObj = {
174
- $schema: 'http://json-schema.org/draft-07/schema#',
175
- title: `Siduri Configuration Schema (${instanceName})`,
176
- type: 'object',
177
- required: ['id', 'name', 'organs'],
178
- additionalProperties: false,
179
- properties: {
180
- $schema: { type: 'string' },
181
- id: { type: 'string', description: 'Unique companion isolation ID' },
182
- name: { type: 'string', description: 'Display name of the companion' },
183
- organs: {
184
- type: 'object',
185
- additionalProperties: false,
186
- properties: organPropertiesSchema,
187
- },
188
- },
189
- };
190
- const siduriSchemaJson = JSON.stringify(schemaObj, null, 2) + '\n';
191
- // 5. .env.example
192
- const envLines = [];
193
- for (const m of manifests) {
194
- if (m.environment && m.environment.length > 0) {
195
- envLines.push(`# ${m.displayName || m.name}`);
196
- for (const envVar of m.environment) {
197
- if (envVar.description) {
198
- envLines.push(`# ${envVar.description}${envVar.required ? ' (required)' : ' (optional)'}`);
199
- }
200
- const defaultVal = envVar.default || '';
201
- envLines.push(`${envVar.name}=${defaultVal}`);
202
- }
203
- envLines.push('');
204
- }
205
- }
206
- const envExample = envLines.length > 0 ? envLines.join('\n') : '# No external environment variables required\n';
207
- // 6. src/index.js
208
- const importLines = [
209
- `import { createServer } from 'node:http';`,
210
- `import { readFile, stat, readdir } from 'node:fs/promises';`,
211
- `import path from 'node:path';`,
212
- `import { fileURLToPath } from 'node:url';`,
213
- `import { SiduriRuntime, dispatchCompanionChat } from '@siduri-x/core';`,
214
- ];
215
- for (const m of manifests) {
216
- importLines.push(`import { ${m.factory} } from '${m.name}';`);
217
- }
218
- const instantiationLines = [];
219
- const organMapEntries = [];
220
- for (const m of manifests) {
221
- const varName = m.configKey;
222
- instantiationLines.push(`const ${varName} = new ${m.factory}(config.organs.${m.configKey});`);
223
- organMapEntries.push(` ${varName},`);
224
- }
225
- const selectedDisplayNames = manifests.map((m) => m.displayName.split(' ')[0] || m.organType).join(', ');
226
- const srcIndexJs = [
227
- ...importLines,
228
- '',
229
- `const __filename = fileURLToPath(import.meta.url);`,
230
- `const __dirname = path.dirname(__filename);`,
231
- `const rootDir = path.resolve(__dirname, '..');`,
232
- '',
233
- `const config = JSON.parse(`,
234
- ` await readFile(path.join(rootDir, 'siduri.config.json'), 'utf8')`,
235
- `);`,
236
- '',
237
- ...instantiationLines,
238
- '',
239
- `const runtime = new SiduriRuntime(config.id, config, {`,
240
- ...organMapEntries,
241
- `});`,
242
- '',
243
- `await runtime.initialize();`,
244
- '',
245
- `const audioCache = new Map();`,
246
- '',
247
- `const server = createServer(async (req, res) => {`,
248
- ` const parsedUrl = new URL(req.url, \`http://\${req.headers.host || 'localhost'}\`);`,
249
- ` const pathname = parsedUrl.pathname;`,
250
- '',
251
- ` // API: Status & Health Probes (minimal safe operational state, no secrets/credentials/config.organs)`,
252
- ` if ((pathname === '/health' || pathname === '/api/status') && req.method === 'GET') {`,
253
- ` res.writeHead(200, { 'Content-Type': 'application/json' });`,
254
- ` res.end(JSON.stringify({`,
255
- ` status: 'ok',`,
256
- ` uptime: process.uptime(),`,
257
- ` }));`,
258
- ` return;`,
259
- ` }`,
260
- '',
261
- ` // API: Audio buffer retrieval for voice playback`,
262
- ` if (pathname.startsWith('/api/audio/') && req.method === 'GET') {`,
263
- ` const audioId = pathname.slice('/api/audio/'.length);`,
264
- ` const buffer = audioCache.get(audioId);`,
265
- ` if (buffer) {`,
266
- ` res.writeHead(200, { 'Content-Type': 'audio/wav' });`,
267
- ` res.end(Buffer.from(buffer));`,
268
- ` return;`,
269
- ` }`,
270
- ` res.writeHead(404, { 'Content-Type': 'application/json' });`,
271
- ` res.end(JSON.stringify({ error: 'Audio not found' }));`,
272
- ` return;`,
273
- ` }`,
274
- '',
275
- ` // API: Memory Claims & Items`,
276
- ` if ((pathname === '/memory' || pathname === '/memory/claims' || pathname === '/api/memory/claims') && req.method === 'GET') {`,
277
- ` res.writeHead(200, { 'Content-Type': 'application/json' });`,
278
- ` try {`,
279
- ` const claims = typeof memory?.getAllClaims === 'function' ? await memory.getAllClaims() : (typeof memory?.getClaims === 'function' ? await memory.getClaims() : []);`,
280
- ` res.end(JSON.stringify({ claims, items: claims }));`,
281
- ` } catch (e) {`,
282
- ` res.end(JSON.stringify({ claims: [], items: [] }));`,
283
- ` }`,
284
- ` return;`,
285
- ` }`,
286
- '',
287
- ` // API: Memory Proposals`,
288
- ` if (pathname === '/memory/proposals' && req.method === 'GET') {`,
289
- ` res.writeHead(200, { 'Content-Type': 'application/json' });`,
290
- ` try {`,
291
- ` const proposals = typeof memory?.getPendingClaims === 'function' ? await memory.getPendingClaims() : [];`,
292
- ` res.end(JSON.stringify({ proposals }));`,
293
- ` } catch (e) {`,
294
- ` res.end(JSON.stringify({ proposals: [] }));`,
295
- ` }`,
296
- ` return;`,
297
- ` }`,
298
- '',
299
- ` // API: Memory Directives`,
300
- ` if ((pathname === '/memory/behavioral' || pathname === '/api/memory/directives') && req.method === 'GET') {`,
301
- ` res.writeHead(200, { 'Content-Type': 'application/json' });`,
302
- ` try {`,
303
- ` const directives = typeof memory?.getDirectives === 'function' ? await memory.getDirectives() : [`,
304
- ` { domain: 'personality', name: 'Active Self Tone', content: 'Warm, empathetic, and thoughtful conversational style.' },`,
305
- ` { domain: 'cognition', name: 'Authoritative Memory', content: 'Ground responses in verified claims and personal history.' }`,
306
- ` ];`,
307
- ` res.end(JSON.stringify({ directives }));`,
308
- ` } catch (e) {`,
309
- ` res.end(JSON.stringify({ directives: [] }));`,
310
- ` }`,
311
- ` return;`,
312
- ` }`,
313
- '',
314
- ` // API: Memory Proposal Approval / Rejection`,
315
- ` if ((pathname === '/memory/proposals/approve' || pathname === '/memory/proposals/reject') && req.method === 'POST') {`,
316
- ` let body = '';`,
317
- ` req.on('data', (chunk) => { body += chunk; });`,
318
- ` req.on('end', async () => {`,
319
- ` try {`,
320
- ` const payload = JSON.parse(body || '{}');`,
321
- ` const claimId = payload.id || payload.claimId;`,
322
- ` if (!claimId) {`,
323
- ` res.writeHead(400, { 'Content-Type': 'application/json' });`,
324
- ` res.end(JSON.stringify({ error: 'Missing required claim id' }));`,
325
- ` return;`,
326
- ` }`,
327
- ` if (pathname.endsWith('approve')) {`,
328
- ` if (typeof memory?.approveClaim === 'function') {`,
329
- ` await memory.approveClaim(claimId);`,
330
- ` }`,
331
- ` res.writeHead(200, { 'Content-Type': 'application/json' });`,
332
- ` res.end(JSON.stringify({ approved: true, id: claimId }));`,
333
- ` } else {`,
334
- ` if (typeof memory?.rejectClaim === 'function') {`,
335
- ` await memory.rejectClaim(claimId);`,
336
- ` }`,
337
- ` res.writeHead(200, { 'Content-Type': 'application/json' });`,
338
- ` res.end(JSON.stringify({ rejected: true, id: claimId }));`,
339
- ` }`,
340
- ` } catch (err) {`,
341
- ` res.writeHead(500, { 'Content-Type': 'application/json' });`,
342
- ` res.end(JSON.stringify({ error: err.message }));`,
343
- ` }`,
344
- ` });`,
345
- ` return;`,
346
- ` }`,
347
- '',
348
- ` // API: Evidence packs`,
349
- ` if (pathname === '/evidence/packs' && req.method === 'GET') {`,
350
- ` res.writeHead(200, { 'Content-Type': 'application/json' });`,
351
- ` res.end(JSON.stringify({ packs: [] }));`,
352
- ` return;`,
353
- ` }`,
354
- '',
355
- ` // API: Chat interaction (routed through canonical dispatchCompanionChat from @siduri-x/core)`,
356
- ` if ((pathname === '/chat' || pathname === '/api/chat') && req.method === 'POST') {`,
357
- ` let body = '';`,
358
- ` req.on('data', (chunk) => { body += chunk; });`,
359
- ` req.on('end', async () => {`,
360
- ` try {`,
361
- ` const payload = JSON.parse(body || '{}');`,
362
- ` const response = await dispatchCompanionChat(runtime, {`,
363
- ` id: config.id,`,
364
- ` companionId: config.id,`,
365
- ` message: payload.message || payload.text || '',`,
366
- ` role: payload.role || 'OWNER',`,
367
- ` history: Array.isArray(payload.history) ? payload.history : [],`,
368
- ` });`,
369
- '',
370
- ` res.writeHead(200, { 'Content-Type': 'application/json' });`,
371
- ` res.end(JSON.stringify(response));`,
372
- ` } catch (err) {`,
373
- ` res.writeHead(500, { 'Content-Type': 'application/json' });`,
374
- ` res.end(JSON.stringify({ error: err.message }));`,
375
- ` }`,
376
- ` });`,
377
- ` return;`,
378
- ` }`,
379
- '',
380
- ` // API: Model Catalog Discovery (Body & Voice)`,
381
- ` if (pathname === '/api/models/body' && req.method === 'GET') {`,
382
- ` res.writeHead(200, { 'Content-Type': 'application/json' });`,
383
- ` try {`,
384
- ` const bodyDir = path.join(rootDir, 'assets', 'body');`,
385
- ` const entries = await readdir(bodyDir, { withFileTypes: true }).catch(() => []);`,
386
- ` const models = entries.filter((e) => e.isDirectory()).map((e) => e.name);`,
387
- ` res.end(JSON.stringify({ models: models.length ? models : ['default'] }));`,
388
- ` } catch {`,
389
- ` res.end(JSON.stringify({ models: ['default'] }));`,
390
- ` }`,
391
- ` return;`,
392
- ` }`,
393
- '',
394
- ` if (pathname === '/api/models/voice' && req.method === 'GET') {`,
395
- ` res.writeHead(200, { 'Content-Type': 'application/json' });`,
396
- ` try {`,
397
- ` const voiceDir = path.join(rootDir, 'assets', 'voice');`,
398
- ` const entries = await readdir(voiceDir, { withFileTypes: true }).catch(() => []);`,
399
- ` const models = entries.filter((e) => e.isDirectory()).map((e) => e.name);`,
400
- ` res.end(JSON.stringify({ models: models.length ? models : ['default'] }));`,
401
- ` } catch {`,
402
- ` res.end(JSON.stringify({ models: ['default'] }));`,
403
- ` }`,
404
- ` return;`,
405
- ` }`,
406
- '',
407
- ` // Static files & Next.js apps/web export routing with strict boundary verification`,
408
- ` let decodedPathname = pathname;`,
409
- ` try {`,
410
- ` while (decodedPathname.includes('%')) {`,
411
- ` const next = decodeURIComponent(decodedPathname);`,
412
- ` if (next === decodedPathname) break;`,
413
- ` decodedPathname = next;`,
414
- ` }`,
415
- ` } catch {`,
416
- ` res.writeHead(400, { 'Content-Type': 'text/plain' });`,
417
- ` res.end('Bad Request');`,
418
- ` return;`,
419
- ` }`,
420
- ` const normalizedPath = path.normalize(decodedPathname).replace(/^[/\\\\]+/, '');`,
421
- ` const canonicalPublicRoot = path.resolve(rootDir, 'public');`,
422
- ` const canonicalAssetsRoot = path.resolve(rootDir, 'assets');`,
423
- ` const candidatePairs = [`,
424
- ` { root: canonicalPublicRoot, target: path.resolve(canonicalPublicRoot, normalizedPath, 'index.html') },`,
425
- ` { root: canonicalPublicRoot, target: path.resolve(canonicalPublicRoot, normalizedPath + '.html') },`,
426
- ` { root: canonicalPublicRoot, target: path.resolve(canonicalPublicRoot, normalizedPath) },`,
427
- ` ];`,
428
- '',
429
- ` if (!normalizedPath || normalizedPath === '.' || normalizedPath === './') {`,
430
- ` candidatePairs.unshift({ root: canonicalPublicRoot, target: path.resolve(canonicalPublicRoot, 'index.html') });`,
431
- ` }`,
432
- '',
433
- ` // Compatibility fallback for legacy /live2d/<modelName>/... -> ./assets/body/<modelName>/...`,
434
- ` if (decodedPathname.startsWith('/live2d/')) {`,
435
- ` const relativeAssetPath = path.normalize(decodedPathname.slice('/live2d/'.length)).replace(/^[/\\\\]+/, '');`,
436
- ` candidatePairs.unshift({ root: canonicalAssetsRoot, target: path.resolve(canonicalAssetsRoot, 'body', relativeAssetPath) });`,
437
- ` candidatePairs.unshift({ root: canonicalAssetsRoot, target: path.resolve(canonicalAssetsRoot, 'body', 'model', relativeAssetPath) });`,
438
- ` }`,
439
- '',
440
- ` for (const { root, target } of candidatePairs) {`,
441
- ` try {`,
442
- ` // Strict path containment check: target must reside within configured root directory`,
443
- ` const relative = path.relative(root, target);`,
444
- ` if (relative.startsWith('..') || path.isAbsolute(relative)) {`,
445
- ` continue;`,
446
- ` }`,
447
- ` const fileStat = await stat(target);`,
448
- ` if (fileStat.isFile()) {`,
449
- ` const ext = path.extname(target).toLowerCase();`,
450
- ` const mimeTypes = {`,
451
- ` '.html': 'text/html; charset=utf-8',`,
452
- ` '.js': 'application/javascript; charset=utf-8',`,
453
- ` '.css': 'text/css; charset=utf-8',`,
454
- ` '.json': 'application/json',`,
455
- ` '.png': 'image/png',`,
456
- ` '.jpg': 'image/jpeg',`,
457
- ` '.svg': 'image/svg+xml',`,
458
- ` '.wav': 'audio/wav',`,
459
- ` '.ico': 'image/x-icon',`,
460
- ` '.txt': 'text/plain; charset=utf-8',`,
461
- ` '.moc3': 'application/octet-stream',`,
462
- ` };`,
463
- ` const contentType = mimeTypes[ext] || 'application/octet-stream';`,
464
- ` const content = await readFile(target);`,
465
- ` res.writeHead(200, { 'Content-Type': contentType });`,
466
- ` res.end(content);`,
467
- ` return;`,
468
- ` }`,
469
- ` } catch (e) {}`,
470
- ` }`,
471
- '',
472
- ` res.writeHead(404, { 'Content-Type': 'text/plain' });`,
473
- ` res.end('Not Found');`,
474
- `});`,
475
- '',
476
- `const PORT = process.env.PORT || 3000;`,
477
- `server.listen(Number(PORT), '127.0.0.1', () => {`,
478
- ` console.log(\`✓ Siduri [\${config.name}] initialized with [${selectedDisplayNames}].\`);`,
479
- ` console.log(\`➜ Web Companion & Memory Console running at: http://127.0.0.1:\${PORT}\`);`,
480
- ` if (process.env.PORT === '0') {`,
481
- ` server.close();`,
482
- ` }`,
483
- `});`,
484
- '',
485
- ].join('\n');
486
- // 7. README.md
487
- const readmeLines = [
488
- `# ${instanceName}`,
489
- '',
490
- `Standalone Siduri AI companion instance generated with explicitly composed organs:`,
491
- '',
492
- ...manifests.map((m) => `- **${m.displayName}** (\`${m.name}\`)`),
493
- '',
494
- '## Prerequisites',
495
- '',
496
- '- **Node.js**: `v20.0.0` or higher',
497
- '- **Environment**: Valid `.env` file (configured from `.env.example`)',
498
- ];
499
- if (hasMemory) {
500
- readmeLines.push('- **Local Services (Optional)**: Docker (or standalone alternatives):');
501
- readmeLines.push(' - **PostgreSQL**: Required for memory claims & durable state (or use cloud Supabase/Neon)');
502
- }
503
- if (isVoicevox) {
504
- readmeLines.push('- **VOICEVOX**: Note: The Voicevox engine executable will be securely auto-downloaded at runtime by Siduri if no local URL is provided.');
505
- }
506
- readmeLines.push('', '## Getting Started', '', '### 1. Install Dependencies', '```bash', 'npm install', '```', '', '### 2. Configure Environment', '```bash', 'cp .env.example .env', '```', 'Fill in your LLM API key (e.g. `OPENROUTER_API_KEY`) and any other service credentials in `.env`.');
507
- if (dockerComposeYaml) {
508
- readmeLines.push('', '### 3. Start Local Services (Docker)', '```bash', 'npm run services:up', '```', '*(To stop services later, run `npm run services:down`)*');
509
- }
510
- if (hasMemory) {
511
- readmeLines.push('', `### ${dockerComposeYaml ? '4' : '3'}. Database Migrations`, 'Ensure `DATABASE_URL` in `.env` is reachable, then push the memory organ PostgreSQL schema:', '```bash', 'npx @vxnus/siduri db push', '```');
512
- }
513
- readmeLines.push('', `### ${hasMemory ? (dockerComposeYaml ? '5' : '4') : (dockerComposeYaml ? '4' : '3')}. Diagnostics & Health Probe`, 'Verify all environment variables, services, and organ connections:', '```bash', 'npm run doctor', '```', '', `### ${hasMemory ? (dockerComposeYaml ? '6' : '5') : (dockerComposeYaml ? '5' : '4')}. Start Companion & Web Console`, 'Launch your companion runtime and Web UI / Memory Control Panel:', '```bash', 'npm start', '```', 'Then open `http://localhost:3000` in your browser.');
514
- const companionSlug = instanceName.toLowerCase().replace(/[^a-z0-9_-]/g, '') || 'default';
515
- const createAssetsDirs = [];
516
- if (hasBody) {
517
- createAssetsDirs.push(`assets/body/${companionSlug}`);
518
- readmeLines.push('', '### Body & Avatar Models', `Place your Live2D Cubism model assets into \`./assets/body/${companionSlug}/\`:`, '- `model.model3.json`', '- `model.moc3`', '- textures directory');
519
- }
520
- if (hasVoice) {
521
- createAssetsDirs.push(`assets/voice/${companionSlug}`);
522
- readmeLines.push('', '### Voice & RVC Models', `Place your character RVC voice models into \`./assets/voice/${companionSlug}/\`:`, `- \`${companionSlug}.pth\` (Target voice weights)`, `- \`${companionSlug}.index\` (Feature index file)`);
523
- }
524
- readmeLines.push('');
525
- const readmeMd = readmeLines.join('\n');
526
- const webHtml = (0, web_template_1.generateWebHtml)(instanceName, manifests);
527
- const result = {
528
- 'package.json': packageJson,
529
- 'siduri.config.json': siduriConfigJson,
530
- 'siduri.schema.json': siduriSchemaJson,
531
- '.env.example': envExample,
532
- 'README.md': readmeMd,
533
- 'src/index.js': srcIndexJs,
534
- 'public/index.html': webHtml,
535
- createAssetsBodyDir: hasBody,
536
- createAssetsDirs,
537
- };
538
- if (dockerComposeYaml) {
539
- result['docker-compose.yml'] = dockerComposeYaml;
540
- }
541
- return result;
542
- }
@@ -1 +0,0 @@
1
- export {};