@vxnus/siduri 0.0.7 → 0.0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -1
- package/dist/builtin-manifests.js +12 -12
- package/dist/clean-machine-e2e.test.js +12 -12
- package/dist/configurators/behavior.d.ts +2 -0
- package/dist/configurators/behavior.js +36 -0
- package/dist/configurators/body.d.ts +2 -0
- package/dist/configurators/body.js +44 -0
- package/dist/configurators/brain.d.ts +6 -0
- package/dist/configurators/brain.js +80 -0
- package/dist/configurators/ear.d.ts +2 -0
- package/dist/configurators/ear.js +28 -0
- package/dist/configurators/hands.d.ts +2 -0
- package/dist/configurators/hands.js +27 -0
- package/dist/configurators/index.d.ts +23 -0
- package/dist/configurators/index.js +74 -0
- package/dist/configurators/knowledge.d.ts +6 -0
- package/dist/configurators/knowledge.js +100 -0
- package/dist/configurators/memory.d.ts +2 -0
- package/dist/configurators/memory.js +44 -0
- package/dist/configurators/observation.d.ts +2 -0
- package/dist/configurators/observation.js +12 -0
- package/dist/configurators/types.d.ts +12 -0
- package/dist/configurators/types.js +2 -0
- package/dist/configurators/vision.d.ts +2 -0
- package/dist/configurators/vision.js +39 -0
- package/dist/configurators/voice.d.ts +2 -0
- package/dist/configurators/voice.js +53 -0
- package/dist/configurators.test.d.ts +1 -0
- package/dist/configurators.test.js +275 -0
- package/dist/doctor-db.test.js +9 -3
- package/dist/generator.d.ts +2 -0
- package/dist/generator.js +289 -33
- package/dist/generator.test.js +20 -1
- package/dist/index.d.ts +16 -0
- package/dist/index.js +165 -54
- package/dist/providers/knowledge-hub.d.ts +37 -0
- package/dist/providers/knowledge-hub.js +141 -0
- package/dist/providers/openrouter.d.ts +32 -0
- package/dist/providers/openrouter.js +201 -0
- package/dist/release-check.js +12 -12
- package/dist/web-dist/404/index.html +1 -0
- package/dist/web-dist/404.html +1 -0
- package/dist/web-dist/__next.__PAGE__.txt +34 -0
- package/dist/web-dist/__next._full.txt +27 -0
- package/dist/web-dist/__next._tree.txt +3 -0
- package/dist/web-dist/_next/static/_zOqKpMPc6RDqk04fUScI/_buildManifest.js +11 -0
- package/dist/web-dist/_next/static/_zOqKpMPc6RDqk04fUScI/_clientMiddlewareManifest.js +1 -0
- package/dist/web-dist/_next/static/_zOqKpMPc6RDqk04fUScI/_ssgManifest.js +1 -0
- package/dist/web-dist/_next/static/chunks/0cz1d0mv5g_q7.js +1 -0
- package/dist/web-dist/_next/static/chunks/0uwih7sydv413.js +1 -0
- package/dist/web-dist/_next/static/chunks/1_yae15ffa5f6.js +1 -0
- package/dist/web-dist/_next/static/chunks/1hz3jco387c-k.js +1 -0
- package/dist/web-dist/_next/static/chunks/2bu5_paf4sm3x.css +1 -0
- package/dist/web-dist/_next/static/chunks/2kcqevsmv6kh2.js +31 -0
- package/dist/web-dist/_next/static/chunks/2s3d1bfr0l4b0.js +1 -0
- package/dist/web-dist/_next/static/chunks/32z87id9k6i2z.js +22 -0
- package/dist/web-dist/_next/static/chunks/39nefv-hczfy7.js +30 -0
- package/dist/web-dist/_next/static/chunks/3bx2gs3idjmo1.js +1 -0
- package/dist/web-dist/_next/static/chunks/turbopack-3eipe4c-imn5l.js +1 -0
- package/dist/web-dist/_next/static/media/favicon.2vob68tjqpejf.ico +0 -0
- package/dist/web-dist/_not-found/__next._full.txt +17 -0
- package/dist/web-dist/_not-found/__next._not-found.__PAGE__.txt +23 -0
- package/dist/web-dist/_not-found/__next._tree.txt +3 -0
- package/dist/web-dist/_not-found/index.html +1 -0
- package/dist/web-dist/_not-found/index.txt +17 -0
- package/dist/web-dist/chat/__next._full.txt +18 -0
- package/dist/web-dist/chat/__next._tree.txt +3 -0
- package/dist/web-dist/chat/__next.chat.__PAGE__.txt +24 -0
- package/dist/web-dist/chat/index.html +1 -0
- package/dist/web-dist/chat/index.txt +18 -0
- package/dist/web-dist/favicon.ico +0 -0
- package/dist/web-dist/index.html +1 -0
- package/dist/web-dist/index.txt +27 -0
- package/dist/web-dist/live2d/akaituno/akaituno.8192/texture_00.png +0 -0
- package/dist/web-dist/live2d/akaituno/akaituno.cdi3.json +296 -0
- package/dist/web-dist/live2d/akaituno/akaituno.moc3 +0 -0
- package/dist/web-dist/live2d/akaituno/akaituno.model3.json +42 -0
- package/dist/web-dist/live2d/akaituno/akaituno.physics3.json +839 -0
- package/dist/web-dist/live2d/akaituno/eye_color.exp3.json +12 -0
- package/dist/web-dist/live2d/akaituno/eyes_zetubou.exp3.json +12 -0
- package/dist/web-dist/live2d/akaituno/face_aozame.exp3.json +12 -0
- package/dist/web-dist/live2d/akaituno/hair_open.exp3.json +12 -0
- package/dist/web-dist/live2d/live2dcubismcore.min.js +9 -0
- package/dist/web-dist/operator/__next._full.txt +18 -0
- package/dist/web-dist/operator/__next._tree.txt +3 -0
- package/dist/web-dist/operator/__next.operator.__PAGE__.txt +24 -0
- package/dist/web-dist/operator/index.html +1 -0
- package/dist/web-dist/operator/index.txt +18 -0
- package/dist/web-template.d.ts +2 -0
- package/dist/web-template.js +547 -0
- package/package.json +7 -7
package/dist/generator.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.generateInstanceFiles = generateInstanceFiles;
|
|
4
|
+
const web_template_1 = require("./web-template");
|
|
4
5
|
function getDefaultConfigForManifest(manifest) {
|
|
5
6
|
const schema = manifest.configSchema || {};
|
|
6
7
|
const props = schema.properties || {};
|
|
@@ -65,29 +66,87 @@ function getDefaultConfigForManifest(manifest) {
|
|
|
65
66
|
function generateInstanceFiles(options) {
|
|
66
67
|
const instanceName = options.name || 'my-siduri';
|
|
67
68
|
const instanceId = options.id || 'default';
|
|
68
|
-
const coreVersion = options.coreVersion || '^1.0.
|
|
69
|
+
const coreVersion = options.coreVersion || '^1.0.1';
|
|
69
70
|
const manifests = options.selectedManifests;
|
|
70
|
-
|
|
71
|
+
const hasMemory = manifests.some((m) => m.organType === 'memory');
|
|
72
|
+
const hasVoice = manifests.some((m) => m.organType === 'voice');
|
|
73
|
+
const hasBody = manifests.some((m) => m.organType === 'body');
|
|
74
|
+
const voiceConfig = options.organConfigs?.voice || options.organConfigs?.['@siduri-x/voice'];
|
|
75
|
+
const isVoicevox = hasVoice && (!voiceConfig || voiceConfig.provider === 'voicevox');
|
|
76
|
+
const memoryConfig = options.organConfigs?.memory || options.organConfigs?.['@siduri-x/memory'];
|
|
77
|
+
const isPostgresLocal = hasMemory && (!memoryConfig || memoryConfig.deployment === 'local' || memoryConfig.provider === 'postgres');
|
|
78
|
+
// 1. Optional docker-compose.yml
|
|
79
|
+
let dockerComposeYaml;
|
|
80
|
+
const dockerServices = [];
|
|
81
|
+
const dockerVolumes = [];
|
|
82
|
+
if (hasMemory && isPostgresLocal) {
|
|
83
|
+
dockerServices.push([
|
|
84
|
+
' db:',
|
|
85
|
+
' image: postgres:15',
|
|
86
|
+
' environment:',
|
|
87
|
+
' POSTGRES_USER: postgres',
|
|
88
|
+
' POSTGRES_PASSWORD: password',
|
|
89
|
+
' POSTGRES_DB: siduri',
|
|
90
|
+
' ports:',
|
|
91
|
+
' - "5432:5432"',
|
|
92
|
+
' volumes:',
|
|
93
|
+
' - postgres_data:/var/lib/postgresql/data',
|
|
94
|
+
' healthcheck:',
|
|
95
|
+
' test: ["CMD-SHELL", "pg_isready -U postgres"]',
|
|
96
|
+
' interval: 2s',
|
|
97
|
+
' timeout: 5s',
|
|
98
|
+
' retries: 5',
|
|
99
|
+
].join('\n'));
|
|
100
|
+
dockerVolumes.push(' postgres_data:');
|
|
101
|
+
}
|
|
102
|
+
if (isVoicevox) {
|
|
103
|
+
dockerServices.push([
|
|
104
|
+
' voicevox:',
|
|
105
|
+
' image: voicevox/voicevox_engine:cpu-latest',
|
|
106
|
+
' ports:',
|
|
107
|
+
' - "50021:50021"',
|
|
108
|
+
].join('\n'));
|
|
109
|
+
}
|
|
110
|
+
if (dockerServices.length > 0) {
|
|
111
|
+
const composeLines = [
|
|
112
|
+
'version: "3.8"',
|
|
113
|
+
'',
|
|
114
|
+
'services:',
|
|
115
|
+
...dockerServices,
|
|
116
|
+
];
|
|
117
|
+
if (dockerVolumes.length > 0) {
|
|
118
|
+
composeLines.push('', 'volumes:', ...dockerVolumes);
|
|
119
|
+
}
|
|
120
|
+
composeLines.push('');
|
|
121
|
+
dockerComposeYaml = composeLines.join('\n');
|
|
122
|
+
}
|
|
123
|
+
// 2. package.json
|
|
71
124
|
const dependencies = {
|
|
72
125
|
'@siduri-x/core': coreVersion,
|
|
73
126
|
};
|
|
74
127
|
for (const m of manifests) {
|
|
75
|
-
dependencies[m.name] = `^${m.version || '1.0.
|
|
128
|
+
dependencies[m.name] = `^${m.version || '1.0.1'}`;
|
|
129
|
+
}
|
|
130
|
+
const scripts = {
|
|
131
|
+
start: 'node src/index.js',
|
|
132
|
+
dev: 'node --watch src/index.js',
|
|
133
|
+
doctor: 'siduri doctor',
|
|
134
|
+
db: 'siduri db',
|
|
135
|
+
};
|
|
136
|
+
if (dockerComposeYaml) {
|
|
137
|
+
scripts['services:up'] = 'docker compose up -d';
|
|
138
|
+
scripts['services:down'] = 'docker compose down';
|
|
139
|
+
scripts['services:logs'] = 'docker compose logs -f';
|
|
76
140
|
}
|
|
77
141
|
const packageJsonObj = {
|
|
78
142
|
name: instanceName.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '') || 'my-siduri',
|
|
79
143
|
private: true,
|
|
80
144
|
type: 'module',
|
|
81
|
-
scripts
|
|
82
|
-
start: 'node src/index.js',
|
|
83
|
-
dev: 'node --watch src/index.js',
|
|
84
|
-
doctor: 'siduri doctor',
|
|
85
|
-
db: 'siduri db',
|
|
86
|
-
},
|
|
145
|
+
scripts,
|
|
87
146
|
dependencies,
|
|
88
147
|
};
|
|
89
148
|
const packageJson = JSON.stringify(packageJsonObj, null, 2) + '\n';
|
|
90
|
-
//
|
|
149
|
+
// 3. siduri.config.json
|
|
91
150
|
const organsConfig = {};
|
|
92
151
|
for (const m of manifests) {
|
|
93
152
|
const customConfig = options.organConfigs?.[m.configKey] || options.organConfigs?.[m.organType];
|
|
@@ -100,7 +159,7 @@ function generateInstanceFiles(options) {
|
|
|
100
159
|
organs: organsConfig,
|
|
101
160
|
};
|
|
102
161
|
const siduriConfigJson = JSON.stringify(configObj, null, 2) + '\n';
|
|
103
|
-
//
|
|
162
|
+
// 4. siduri.schema.json
|
|
104
163
|
const organPropertiesSchema = {};
|
|
105
164
|
for (const m of manifests) {
|
|
106
165
|
organPropertiesSchema[m.configKey] = m.configSchema || { type: 'object' };
|
|
@@ -123,7 +182,7 @@ function generateInstanceFiles(options) {
|
|
|
123
182
|
},
|
|
124
183
|
};
|
|
125
184
|
const siduriSchemaJson = JSON.stringify(schemaObj, null, 2) + '\n';
|
|
126
|
-
//
|
|
185
|
+
// 5. .env.example
|
|
127
186
|
const envLines = [];
|
|
128
187
|
for (const m of manifests) {
|
|
129
188
|
if (m.environment && m.environment.length > 0) {
|
|
@@ -139,9 +198,12 @@ function generateInstanceFiles(options) {
|
|
|
139
198
|
}
|
|
140
199
|
}
|
|
141
200
|
const envExample = envLines.length > 0 ? envLines.join('\n') : '# No external environment variables required\n';
|
|
142
|
-
//
|
|
201
|
+
// 6. src/index.js
|
|
143
202
|
const importLines = [
|
|
144
|
-
`import {
|
|
203
|
+
`import { createServer } from 'node:http';`,
|
|
204
|
+
`import { readFile, stat } from 'node:fs/promises';`,
|
|
205
|
+
`import path from 'node:path';`,
|
|
206
|
+
`import { fileURLToPath } from 'node:url';`,
|
|
145
207
|
`import { SiduriRuntime } from '@siduri-x/core';`,
|
|
146
208
|
];
|
|
147
209
|
for (const m of manifests) {
|
|
@@ -158,8 +220,12 @@ function generateInstanceFiles(options) {
|
|
|
158
220
|
const srcIndexJs = [
|
|
159
221
|
...importLines,
|
|
160
222
|
'',
|
|
223
|
+
`const __filename = fileURLToPath(import.meta.url);`,
|
|
224
|
+
`const __dirname = path.dirname(__filename);`,
|
|
225
|
+
`const rootDir = path.resolve(__dirname, '..');`,
|
|
226
|
+
'',
|
|
161
227
|
`const config = JSON.parse(`,
|
|
162
|
-
` await readFile(
|
|
228
|
+
` await readFile(path.join(rootDir, 'siduri.config.json'), 'utf8')`,
|
|
163
229
|
`);`,
|
|
164
230
|
'',
|
|
165
231
|
...instantiationLines,
|
|
@@ -170,46 +236,236 @@ function generateInstanceFiles(options) {
|
|
|
170
236
|
'',
|
|
171
237
|
`await runtime.initialize();`,
|
|
172
238
|
'',
|
|
173
|
-
`
|
|
239
|
+
`const audioCache = new Map();`,
|
|
240
|
+
'',
|
|
241
|
+
`const server = createServer(async (req, res) => {`,
|
|
242
|
+
` const parsedUrl = new URL(req.url, \`http://\${req.headers.host || 'localhost'}\`);`,
|
|
243
|
+
` const pathname = parsedUrl.pathname;`,
|
|
244
|
+
'',
|
|
245
|
+
` // API: Status & Health Probes`,
|
|
246
|
+
` if ((pathname === '/health' || pathname === '/api/status') && req.method === 'GET') {`,
|
|
247
|
+
` res.writeHead(200, { 'Content-Type': 'application/json' });`,
|
|
248
|
+
` res.end(JSON.stringify({`,
|
|
249
|
+
` status: 'ok',`,
|
|
250
|
+
` name: config.name,`,
|
|
251
|
+
` id: config.id,`,
|
|
252
|
+
` organs: config.organs,`,
|
|
253
|
+
` uptime: process.uptime(),`,
|
|
254
|
+
` }));`,
|
|
255
|
+
` return;`,
|
|
256
|
+
` }`,
|
|
257
|
+
'',
|
|
258
|
+
` // API: Audio buffer retrieval for voice playback`,
|
|
259
|
+
` if (pathname.startsWith('/api/audio/') && req.method === 'GET') {`,
|
|
260
|
+
` const audioId = pathname.slice('/api/audio/'.length);`,
|
|
261
|
+
` const buffer = audioCache.get(audioId);`,
|
|
262
|
+
` if (buffer) {`,
|
|
263
|
+
` res.writeHead(200, { 'Content-Type': 'audio/wav' });`,
|
|
264
|
+
` res.end(Buffer.from(buffer));`,
|
|
265
|
+
` return;`,
|
|
266
|
+
` }`,
|
|
267
|
+
` res.writeHead(404, { 'Content-Type': 'application/json' });`,
|
|
268
|
+
` res.end(JSON.stringify({ error: 'Audio not found' }));`,
|
|
269
|
+
` return;`,
|
|
270
|
+
` }`,
|
|
271
|
+
'',
|
|
272
|
+
` // API: Memory Claims & Items`,
|
|
273
|
+
` if ((pathname === '/memory' || pathname === '/memory/claims' || pathname === '/api/memory/claims') && req.method === 'GET') {`,
|
|
274
|
+
` res.writeHead(200, { 'Content-Type': 'application/json' });`,
|
|
275
|
+
` try {`,
|
|
276
|
+
` const claims = typeof memory?.getAllClaims === 'function' ? await memory.getAllClaims() : (typeof memory?.getClaims === 'function' ? await memory.getClaims() : []);`,
|
|
277
|
+
` res.end(JSON.stringify({ claims, items: claims }));`,
|
|
278
|
+
` } catch (e) {`,
|
|
279
|
+
` res.end(JSON.stringify({ claims: [], items: [] }));`,
|
|
280
|
+
` }`,
|
|
281
|
+
` return;`,
|
|
282
|
+
` }`,
|
|
283
|
+
'',
|
|
284
|
+
` // API: Memory Proposals`,
|
|
285
|
+
` if (pathname === '/memory/proposals' && req.method === 'GET') {`,
|
|
286
|
+
` res.writeHead(200, { 'Content-Type': 'application/json' });`,
|
|
287
|
+
` try {`,
|
|
288
|
+
` const proposals = typeof memory?.getPendingClaims === 'function' ? await memory.getPendingClaims() : [];`,
|
|
289
|
+
` res.end(JSON.stringify({ proposals }));`,
|
|
290
|
+
` } catch (e) {`,
|
|
291
|
+
` res.end(JSON.stringify({ proposals: [] }));`,
|
|
292
|
+
` }`,
|
|
293
|
+
` return;`,
|
|
294
|
+
` }`,
|
|
295
|
+
'',
|
|
296
|
+
` // API: Memory Directives`,
|
|
297
|
+
` if ((pathname === '/memory/behavioral' || pathname === '/api/memory/directives') && req.method === 'GET') {`,
|
|
298
|
+
` res.writeHead(200, { 'Content-Type': 'application/json' });`,
|
|
299
|
+
` try {`,
|
|
300
|
+
` const directives = typeof memory?.getDirectives === 'function' ? await memory.getDirectives() : [`,
|
|
301
|
+
` { domain: 'personality', name: 'Active Self Tone', content: 'Warm, empathetic, and thoughtful conversational style.' },`,
|
|
302
|
+
` { domain: 'cognition', name: 'Authoritative Memory', content: 'Ground responses in verified claims and personal history.' }`,
|
|
303
|
+
` ];`,
|
|
304
|
+
` res.end(JSON.stringify({ directives }));`,
|
|
305
|
+
` } catch (e) {`,
|
|
306
|
+
` res.end(JSON.stringify({ directives: [] }));`,
|
|
307
|
+
` }`,
|
|
308
|
+
` return;`,
|
|
309
|
+
` }`,
|
|
310
|
+
'',
|
|
311
|
+
` // API: Memory Proposal Approval / Rejection`,
|
|
312
|
+
` if ((pathname === '/memory/proposals/approve' || pathname === '/memory/proposals/reject') && req.method === 'POST') {`,
|
|
313
|
+
` res.writeHead(200, { 'Content-Type': 'application/json' });`,
|
|
314
|
+
` res.end(JSON.stringify({ success: true, approved: pathname.endsWith('approve') }));`,
|
|
315
|
+
` return;`,
|
|
316
|
+
` }`,
|
|
317
|
+
'',
|
|
318
|
+
` // API: Evidence packs`,
|
|
319
|
+
` if (pathname === '/evidence/packs' && req.method === 'GET') {`,
|
|
320
|
+
` res.writeHead(200, { 'Content-Type': 'application/json' });`,
|
|
321
|
+
` res.end(JSON.stringify({ packs: [] }));`,
|
|
322
|
+
` return;`,
|
|
323
|
+
` }`,
|
|
324
|
+
'',
|
|
325
|
+
` // API: Chat interaction (supports both /chat and /api/chat)`,
|
|
326
|
+
` if ((pathname === '/chat' || pathname === '/api/chat') && req.method === 'POST') {`,
|
|
327
|
+
` let body = '';`,
|
|
328
|
+
` req.on('data', (chunk) => { body += chunk; });`,
|
|
329
|
+
` req.on('end', async () => {`,
|
|
330
|
+
` try {`,
|
|
331
|
+
` const payload = JSON.parse(body || '{}');`,
|
|
332
|
+
` const userMessage = payload.message || payload.text || '';`,
|
|
333
|
+
` let reply = \`Hello! I received: "\${userMessage}"\`;`,
|
|
334
|
+
` let expression = 'neutral';`,
|
|
335
|
+
` let audioUrl = undefined;`,
|
|
336
|
+
'',
|
|
337
|
+
` if (typeof brain?.generatePlan === 'function') {`,
|
|
338
|
+
` try {`,
|
|
339
|
+
` const plan = await brain.generatePlan({ prompt: userMessage });`,
|
|
340
|
+
` reply = plan.speech || plan.text || reply;`,
|
|
341
|
+
` } catch (err) {`,
|
|
342
|
+
` reply = \`Thinking about "\${userMessage}"... (Brain active)\`;`,
|
|
343
|
+
` }`,
|
|
344
|
+
` }`,
|
|
345
|
+
'',
|
|
346
|
+
` if (typeof voice?.synthesize === 'function') {`,
|
|
347
|
+
` try {`,
|
|
348
|
+
` const wavData = await voice.synthesize(reply);`,
|
|
349
|
+
` const audioId = \`audio_\${Date.now()}\`;`,
|
|
350
|
+
` audioCache.set(audioId, wavData);`,
|
|
351
|
+
` audioUrl = \`/api/audio/\${audioId}\`;`,
|
|
352
|
+
` } catch (e) {}`,
|
|
353
|
+
` }`,
|
|
354
|
+
'',
|
|
355
|
+
` if (typeof body?.setExpression === 'function') {`,
|
|
356
|
+
` expression = reply.includes('!') ? 'happy' : 'calm';`,
|
|
357
|
+
` body.setExpression(expression);`,
|
|
358
|
+
` }`,
|
|
359
|
+
'',
|
|
360
|
+
` res.writeHead(200, { 'Content-Type': 'application/json' });`,
|
|
361
|
+
` res.end(JSON.stringify({ reply, text: reply, expression, audioUrl, status: 'ok' }));`,
|
|
362
|
+
` } catch (err) {`,
|
|
363
|
+
` res.writeHead(500, { 'Content-Type': 'application/json' });`,
|
|
364
|
+
` res.end(JSON.stringify({ error: err.message }));`,
|
|
365
|
+
` }`,
|
|
366
|
+
` });`,
|
|
367
|
+
` return;`,
|
|
368
|
+
` }`,
|
|
369
|
+
'',
|
|
370
|
+
` // Static files & Next.js apps/web export routing`,
|
|
371
|
+
` const normalizedPath = pathname.replace(/^\/+|\/+$/g, '');`,
|
|
372
|
+
` const candidatePaths = [`,
|
|
373
|
+
` path.join(rootDir, 'public', normalizedPath, 'index.html'),`,
|
|
374
|
+
` path.join(rootDir, 'public', normalizedPath + '.html'),`,
|
|
375
|
+
` path.join(rootDir, 'public', normalizedPath),`,
|
|
376
|
+
` path.join(rootDir, normalizedPath),`,
|
|
377
|
+
` ];`,
|
|
378
|
+
'',
|
|
379
|
+
` if (!normalizedPath) {`,
|
|
380
|
+
` candidatePaths.unshift(path.join(rootDir, 'public', 'index.html'));`,
|
|
381
|
+
` }`,
|
|
382
|
+
'',
|
|
383
|
+
` for (const candidate of candidatePaths) {`,
|
|
384
|
+
` try {`,
|
|
385
|
+
` const fileStat = await stat(candidate);`,
|
|
386
|
+
` if (fileStat.isFile()) {`,
|
|
387
|
+
` const ext = path.extname(candidate).toLowerCase();`,
|
|
388
|
+
` const mimeTypes = {`,
|
|
389
|
+
` '.html': 'text/html; charset=utf-8',`,
|
|
390
|
+
` '.js': 'application/javascript; charset=utf-8',`,
|
|
391
|
+
` '.css': 'text/css; charset=utf-8',`,
|
|
392
|
+
` '.json': 'application/json',`,
|
|
393
|
+
` '.png': 'image/png',`,
|
|
394
|
+
` '.jpg': 'image/jpeg',`,
|
|
395
|
+
` '.svg': 'image/svg+xml',`,
|
|
396
|
+
` '.wav': 'audio/wav',`,
|
|
397
|
+
` '.ico': 'image/x-icon',`,
|
|
398
|
+
` '.txt': 'text/plain; charset=utf-8',`,
|
|
399
|
+
` '.moc3': 'application/octet-stream',`,
|
|
400
|
+
` };`,
|
|
401
|
+
` const contentType = mimeTypes[ext] || 'application/octet-stream';`,
|
|
402
|
+
` const content = await readFile(candidate);`,
|
|
403
|
+
` res.writeHead(200, { 'Content-Type': contentType });`,
|
|
404
|
+
` res.end(content);`,
|
|
405
|
+
` return;`,
|
|
406
|
+
` }`,
|
|
407
|
+
` } catch (e) {}`,
|
|
408
|
+
` }`,
|
|
409
|
+
'',
|
|
410
|
+
` res.writeHead(404, { 'Content-Type': 'text/plain' });`,
|
|
411
|
+
` res.end('Not Found');`,
|
|
412
|
+
`});`,
|
|
413
|
+
'',
|
|
414
|
+
`const PORT = process.env.PORT || 3000;`,
|
|
415
|
+
`server.listen(PORT, () => {`,
|
|
416
|
+
` console.log(\`✓ Siduri [\${config.name}] initialized with [${selectedDisplayNames}].\`);`,
|
|
417
|
+
` console.log(\`➜ Web Companion & Memory Console running at: http://localhost:\${PORT}\`);`,
|
|
418
|
+
`});`,
|
|
174
419
|
'',
|
|
175
420
|
].join('\n');
|
|
176
|
-
//
|
|
421
|
+
// 7. README.md
|
|
177
422
|
const readmeLines = [
|
|
178
423
|
`# ${instanceName}`,
|
|
179
424
|
'',
|
|
180
|
-
`Standalone Siduri instance generated with explicitly composed organs:`,
|
|
425
|
+
`Standalone Siduri AI companion instance generated with explicitly composed organs:`,
|
|
181
426
|
'',
|
|
182
427
|
...manifests.map((m) => `- **${m.displayName}** (\`${m.name}\`)`),
|
|
183
428
|
'',
|
|
184
|
-
'##
|
|
185
|
-
'',
|
|
186
|
-
'1. Install dependencies:',
|
|
187
|
-
'```bash',
|
|
188
|
-
'npm install',
|
|
189
|
-
'```',
|
|
429
|
+
'## Prerequisites',
|
|
190
430
|
'',
|
|
191
|
-
'
|
|
192
|
-
'
|
|
193
|
-
'cp .env.example .env',
|
|
194
|
-
'```',
|
|
431
|
+
'- **Node.js**: `v20.0.0` or higher',
|
|
432
|
+
'- **Environment**: Valid `.env` file (configured from `.env.example`)',
|
|
195
433
|
];
|
|
196
|
-
|
|
434
|
+
if (hasMemory || isVoicevox) {
|
|
435
|
+
readmeLines.push('- **Local Services (Optional)**: Docker (or standalone alternatives):');
|
|
436
|
+
if (hasMemory) {
|
|
437
|
+
readmeLines.push(' - **PostgreSQL**: Required for memory claims & durable state (or use cloud Supabase/Neon)');
|
|
438
|
+
}
|
|
439
|
+
if (isVoicevox) {
|
|
440
|
+
readmeLines.push(' - **VOICEVOX**: Required for voice synthesis (or run the official desktop app from [voicevox.hiroshiba.jp](https://voicevox.hiroshiba.jp/))');
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
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`.');
|
|
444
|
+
if (dockerComposeYaml) {
|
|
445
|
+
readmeLines.push('', '### 3. Start Local Services (Docker)', '```bash', 'npm run services:up', '```', '*(To stop services later, run `npm run services:down`)*');
|
|
446
|
+
}
|
|
197
447
|
if (hasMemory) {
|
|
198
|
-
readmeLines.push('',
|
|
448
|
+
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', '```');
|
|
199
449
|
}
|
|
200
|
-
|
|
450
|
+
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.');
|
|
201
451
|
if (hasBody) {
|
|
202
452
|
readmeLines.push('', '### Avatar Assets', 'Place your Live2D Cubism model assets into `./assets/body/model/`:', '- `model.model3.json`', '- `model.moc3`', '- textures directory');
|
|
203
453
|
}
|
|
204
|
-
readmeLines.push(''
|
|
454
|
+
readmeLines.push('');
|
|
205
455
|
const readmeMd = readmeLines.join('\n');
|
|
206
|
-
|
|
456
|
+
const webHtml = (0, web_template_1.generateWebHtml)(instanceName, manifests);
|
|
457
|
+
const result = {
|
|
207
458
|
'package.json': packageJson,
|
|
208
459
|
'siduri.config.json': siduriConfigJson,
|
|
209
460
|
'siduri.schema.json': siduriSchemaJson,
|
|
210
461
|
'.env.example': envExample,
|
|
211
462
|
'README.md': readmeMd,
|
|
212
463
|
'src/index.js': srcIndexJs,
|
|
464
|
+
'public/index.html': webHtml,
|
|
213
465
|
createAssetsBodyDir: hasBody,
|
|
214
466
|
};
|
|
467
|
+
if (dockerComposeYaml) {
|
|
468
|
+
result['docker-compose.yml'] = dockerComposeYaml;
|
|
469
|
+
}
|
|
470
|
+
return result;
|
|
215
471
|
}
|
package/dist/generator.test.js
CHANGED
|
@@ -152,7 +152,26 @@ describe('Instance Generator Composition Invariants (Phase 3)', () => {
|
|
|
152
152
|
expect(pkg.dependencies['@siduri-x/voice']).toBeDefined();
|
|
153
153
|
// Body asset directory requested
|
|
154
154
|
expect(files.createAssetsBodyDir).toBe(true);
|
|
155
|
-
// README mentions Live2D model assets
|
|
155
|
+
// README mentions Live2D model assets & prerequisites
|
|
156
156
|
expect(files['README.md']).toContain('assets/body/model');
|
|
157
|
+
expect(files['README.md']).toContain('Prerequisites');
|
|
158
|
+
// Docker compose generated for memory & voice
|
|
159
|
+
expect(files['docker-compose.yml']).toBeDefined();
|
|
160
|
+
expect(files['docker-compose.yml']).toContain('postgres:15');
|
|
161
|
+
expect(files['docker-compose.yml']).toContain('voicevox/voicevox_engine');
|
|
162
|
+
expect(pkg.scripts['services:up']).toBe('docker compose up -d');
|
|
163
|
+
expect(pkg.scripts['services:down']).toBe('docker compose down');
|
|
164
|
+
});
|
|
165
|
+
test('Composition E: Brain only has no docker-compose.yml', () => {
|
|
166
|
+
const files = (0, generator_1.generateInstanceFiles)({
|
|
167
|
+
name: 'brain-solo',
|
|
168
|
+
selectedManifests: [MOCK_MANIFESTS.brain],
|
|
169
|
+
});
|
|
170
|
+
expect(files['docker-compose.yml']).toBeUndefined();
|
|
171
|
+
const pkg = JSON.parse(files['package.json']);
|
|
172
|
+
expect(pkg.scripts['services:up']).toBeUndefined();
|
|
173
|
+
expect(files['public/index.html']).toBeDefined();
|
|
174
|
+
expect(files['public/index.html']).toContain('Memory Console');
|
|
175
|
+
expect(files['public/index.html']).toContain('Companion Chat');
|
|
157
176
|
});
|
|
158
177
|
});
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,20 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import { OrganManifest } from './manifest';
|
|
3
|
+
export declare const CLI_VERSION = "0.0.9";
|
|
4
|
+
export declare const colors: {
|
|
5
|
+
cyan: string;
|
|
6
|
+
dim: string;
|
|
7
|
+
green: string;
|
|
8
|
+
yellow: string;
|
|
9
|
+
bold: string;
|
|
10
|
+
reset: string;
|
|
11
|
+
};
|
|
12
|
+
export declare function printHeader(): void;
|
|
13
|
+
export declare function printSection(title: string): void;
|
|
14
|
+
export declare function printSuccess(message: string): void;
|
|
15
|
+
export declare function projectDirectoryName(value: string): string;
|
|
16
|
+
export declare function formatReviewSummary(companionName: string, selectedManifests: OrganManifest[], organSummaries: Record<string, Record<string, unknown>>): string;
|
|
17
|
+
export declare function withTask<T>(label: string, task: () => Promise<T>): Promise<T>;
|
|
2
18
|
export declare function runCreateWizard(targetDir?: string): Promise<void>;
|
|
3
19
|
export declare function runCliDoctor(targetDir?: string): Promise<void>;
|
|
4
20
|
export declare function runCliDb(subcommand?: string, targetDir?: string): Promise<void>;
|