@vxnus/siduri 0.0.1 → 0.0.3
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 +34 -1
- package/dist/index.js +98 -7
- package/dist/runtime.js +1523 -0
- package/package.json +10 -4
package/README.md
CHANGED
|
@@ -2,12 +2,45 @@
|
|
|
2
2
|
|
|
3
3
|
Experimental CLI for creating and configuring Siduri companions.
|
|
4
4
|
|
|
5
|
+
Requires Node.js 20 or newer.
|
|
6
|
+
|
|
5
7
|
```bash
|
|
6
|
-
npx @vxnus/siduri@0.0.
|
|
8
|
+
npx @vxnus/siduri@0.0.3 create
|
|
7
9
|
```
|
|
8
10
|
|
|
11
|
+
The companion name becomes the project directory. For example, answering
|
|
12
|
+
`Ganyu` creates `./ganyu/siduri.config.json` from the current directory.
|
|
13
|
+
|
|
9
14
|
The wizard configures the required Brain and Memory organs, then lets you
|
|
10
15
|
enable or disable Voice, Knowledge, Behavior, Body, and Vision. Knowledge can
|
|
11
16
|
come from an installed E pack, an E Hub distribution, or a hosted provider.
|
|
12
17
|
|
|
18
|
+
Brain providers:
|
|
19
|
+
|
|
20
|
+
- **OpenRouter** — managed model routing using `OPENROUTER_API_KEY`.
|
|
21
|
+
- **OpenAI-compatible API** — a custom `baseUrl`, model ID, and API-key
|
|
22
|
+
environment variable.
|
|
23
|
+
|
|
24
|
+
Memory currently uses PostgreSQL. The wizard lets you choose Local PostgreSQL,
|
|
25
|
+
Neon, Supabase, or another PostgreSQL provider; all use `DATABASE_URL`. SQLite
|
|
26
|
+
is shown as a future option but is not selectable in this release.
|
|
27
|
+
|
|
28
|
+
The wizard creates a project directory from the companion name, writes
|
|
29
|
+
`siduri.config.json`, copies the Siduri runtime, and installs the runtime
|
|
30
|
+
dependencies. API keys are never written to the configuration file. Optional
|
|
31
|
+
organs can be configured as `{ "provider": "none" }`; Brain and Memory remain
|
|
32
|
+
required.
|
|
33
|
+
|
|
34
|
+
After setup, start the generated instance with:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
cd ganyu
|
|
38
|
+
npm run start
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
For local development, build the CLI from the repository root with
|
|
42
|
+
`pnpm --filter @vxnus/siduri build`. For the full architecture, see the
|
|
43
|
+
[CLI documentation](../docs/cli.md) and
|
|
44
|
+
[configuration reference](../docs/configuration.md).
|
|
45
|
+
|
|
13
46
|
This release is experimental and is not intended for production use.
|
package/dist/index.js
CHANGED
|
@@ -14,7 +14,16 @@ const inquirer_1 = __importDefault(require("inquirer"));
|
|
|
14
14
|
const e_knowledge_1 = require("@vxnus/e-knowledge");
|
|
15
15
|
const execFile = (0, node_util_1.promisify)(node_child_process_1.execFile);
|
|
16
16
|
const DEFAULT_REGISTRY_URL = 'https://e.vxnus.xyz/api/packs';
|
|
17
|
-
const CLI_VERSION = '0.0.
|
|
17
|
+
const CLI_VERSION = '0.0.3';
|
|
18
|
+
const RUNTIME_DEPENDENCIES = {
|
|
19
|
+
'@vxnus/e': '^0.1.3',
|
|
20
|
+
'@vxnus/e-knowledge': '^0.1.2',
|
|
21
|
+
cors: '^2.8.5',
|
|
22
|
+
express: '^4.18.2',
|
|
23
|
+
pg: '^8.23.0',
|
|
24
|
+
ws: '^8.21.3',
|
|
25
|
+
zod: '^4.4.3',
|
|
26
|
+
};
|
|
18
27
|
const colors = {
|
|
19
28
|
cyan: '\u001b[36m',
|
|
20
29
|
dim: '\u001b[2m',
|
|
@@ -24,7 +33,7 @@ const colors = {
|
|
|
24
33
|
};
|
|
25
34
|
function printHeader() {
|
|
26
35
|
console.log(`\n${colors.cyan}◈ SIDURI${colors.reset} ${colors.dim}companion setup${colors.reset}`);
|
|
27
|
-
console.log(`${colors.yellow}Experimental release 0.0.
|
|
36
|
+
console.log(`${colors.yellow}Experimental release 0.0.3${colors.reset} · configuration may change\n`);
|
|
28
37
|
}
|
|
29
38
|
function printSection(title) {
|
|
30
39
|
console.log(`\n${colors.cyan}── ${title} ${'─'.repeat(Math.max(2, 42 - title.length))}${colors.reset}`);
|
|
@@ -32,6 +41,36 @@ function printSection(title) {
|
|
|
32
41
|
function printSuccess(message) {
|
|
33
42
|
console.log(`${colors.green}✓${colors.reset} ${message}`);
|
|
34
43
|
}
|
|
44
|
+
function runtimePath() {
|
|
45
|
+
const projectRuntime = node_path_1.default.join(process.cwd(), 'siduri-runtime.js');
|
|
46
|
+
return node_path_1.default.resolve(pathExists(projectRuntime) ? projectRuntime : node_path_1.default.join(__dirname, 'runtime.js'));
|
|
47
|
+
}
|
|
48
|
+
function pathExists(filePath) {
|
|
49
|
+
try {
|
|
50
|
+
require('node:fs').accessSync(filePath);
|
|
51
|
+
return true;
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
async function startRuntime() {
|
|
58
|
+
const filePath = runtimePath();
|
|
59
|
+
if (!pathExists(filePath)) {
|
|
60
|
+
throw new Error('Siduri runtime bundle is missing. Reinstall the CLI or rebuild the package.');
|
|
61
|
+
}
|
|
62
|
+
await new Promise((resolve, reject) => {
|
|
63
|
+
const child = (0, node_child_process_1.spawn)(process.execPath, [filePath], { stdio: 'inherit', env: process.env });
|
|
64
|
+
child.once('error', reject);
|
|
65
|
+
child.once('exit', (code, signal) => {
|
|
66
|
+
if (signal)
|
|
67
|
+
process.exitCode = 1;
|
|
68
|
+
else if (code !== null)
|
|
69
|
+
process.exitCode = code;
|
|
70
|
+
resolve();
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
}
|
|
35
74
|
async function withTask(label, task) {
|
|
36
75
|
process.stdout.write(`${colors.dim}${label}${colors.reset}`);
|
|
37
76
|
const frames = ['·', '•', '●', '•'];
|
|
@@ -66,6 +105,14 @@ function urlValue(value) {
|
|
|
66
105
|
function safePart(value) {
|
|
67
106
|
return value.replace(/[^a-zA-Z0-9._-]/g, '_');
|
|
68
107
|
}
|
|
108
|
+
function projectDirectoryName(value) {
|
|
109
|
+
const slug = value
|
|
110
|
+
.trim()
|
|
111
|
+
.toLowerCase()
|
|
112
|
+
.replace(/[^a-z0-9]+/g, '-')
|
|
113
|
+
.replace(/^-+|-+$/g, '');
|
|
114
|
+
return slug || 'siduri';
|
|
115
|
+
}
|
|
69
116
|
async function getJson(url) {
|
|
70
117
|
const controller = new AbortController();
|
|
71
118
|
const timeout = setTimeout(() => controller.abort(), 15000);
|
|
@@ -232,9 +279,14 @@ async function main() {
|
|
|
232
279
|
console.log(CLI_VERSION);
|
|
233
280
|
return;
|
|
234
281
|
}
|
|
282
|
+
if (command === 'start') {
|
|
283
|
+
await startRuntime();
|
|
284
|
+
return;
|
|
285
|
+
}
|
|
235
286
|
if (command !== 'create') {
|
|
236
287
|
printHeader();
|
|
237
288
|
console.log('Usage: npx @vxnus/siduri create');
|
|
289
|
+
console.log(' npx @vxnus/siduri start');
|
|
238
290
|
console.log(' npx @vxnus/siduri --version');
|
|
239
291
|
return;
|
|
240
292
|
}
|
|
@@ -242,9 +294,30 @@ async function main() {
|
|
|
242
294
|
printSection('Companion');
|
|
243
295
|
const answers = await inquirer_1.default.prompt([
|
|
244
296
|
{ type: 'input', name: 'name', message: 'Companion name:', default: 'Siduri', validate: nonEmpty },
|
|
245
|
-
{
|
|
297
|
+
{
|
|
298
|
+
type: 'list',
|
|
299
|
+
name: 'memoryEngine',
|
|
300
|
+
message: 'Memory database?',
|
|
301
|
+
choices: [
|
|
302
|
+
{ name: 'PostgreSQL', value: 'postgres' },
|
|
303
|
+
{ name: 'SQLite (future)', value: 'sqlite', disabled: 'Coming soon' },
|
|
304
|
+
],
|
|
305
|
+
},
|
|
246
306
|
]);
|
|
247
|
-
|
|
307
|
+
const { memoryDeployment } = await inquirer_1.default.prompt({
|
|
308
|
+
type: 'list',
|
|
309
|
+
name: 'memoryDeployment',
|
|
310
|
+
message: 'PostgreSQL deployment?',
|
|
311
|
+
choices: [
|
|
312
|
+
{ name: 'Local PostgreSQL', value: 'local' },
|
|
313
|
+
{ name: 'Neon', value: 'neon' },
|
|
314
|
+
{ name: 'Supabase', value: 'supabase' },
|
|
315
|
+
{ name: 'Other PostgreSQL provider', value: 'other' },
|
|
316
|
+
],
|
|
317
|
+
});
|
|
318
|
+
const projectPath = node_path_1.default.resolve(process.cwd(), projectDirectoryName(answers.name));
|
|
319
|
+
await (0, promises_1.mkdir)(projectPath, { recursive: true });
|
|
320
|
+
printSuccess(`${answers.name} · PostgreSQL / ${memoryDeployment} · ${projectPath}`);
|
|
248
321
|
printSection('Brain · required');
|
|
249
322
|
const { brainProvider } = await inquirer_1.default.prompt({
|
|
250
323
|
type: 'list',
|
|
@@ -291,13 +364,13 @@ async function main() {
|
|
|
291
364
|
name: answers.name,
|
|
292
365
|
brain,
|
|
293
366
|
voice: { provider: voice, speakerId: 1 },
|
|
294
|
-
memory: { provider: answers.
|
|
367
|
+
memory: { provider: answers.memoryEngine, deployment: memoryDeployment },
|
|
295
368
|
knowledge,
|
|
296
369
|
behavior: { provider: remaining.behavior === 'none' ? 'none' : 'active_self', preset: remaining.behavior },
|
|
297
370
|
body: { provider: remaining.body, vtsUrl: process.env.VTS_URL || 'ws://127.0.0.1:8001' },
|
|
298
371
|
vision: { provider: remaining.vision, model: 'gpt-4-vision' },
|
|
299
372
|
};
|
|
300
|
-
const configPath = node_path_1.default.join(
|
|
373
|
+
const configPath = node_path_1.default.join(projectPath, 'siduri.config.json');
|
|
301
374
|
try {
|
|
302
375
|
await (0, promises_1.readFile)(configPath, 'utf8');
|
|
303
376
|
const { overwrite } = await inquirer_1.default.prompt({
|
|
@@ -335,7 +408,25 @@ async function main() {
|
|
|
335
408
|
}
|
|
336
409
|
await (0, promises_1.writeFile)(configPath, JSON.stringify(config, null, 2) + '\n', { mode: 0o600 });
|
|
337
410
|
printSuccess(`Configuration written · ${configPath}`);
|
|
338
|
-
|
|
411
|
+
await (0, promises_1.cp)(node_path_1.default.join(__dirname, 'runtime.js'), node_path_1.default.join(projectPath, 'siduri-runtime.js'));
|
|
412
|
+
await (0, promises_1.writeFile)(node_path_1.default.join(projectPath, 'package.json'), JSON.stringify({
|
|
413
|
+
name: projectDirectoryName(answers.name),
|
|
414
|
+
private: true,
|
|
415
|
+
version: '0.0.0',
|
|
416
|
+
scripts: { start: 'node siduri-runtime.js', dev: 'node siduri-runtime.js' },
|
|
417
|
+
dependencies: RUNTIME_DEPENDENCIES,
|
|
418
|
+
}, null, 2) + '\n', { mode: 0o600 });
|
|
419
|
+
const keyEnv = config.brain.apiKeyEnv || 'OPENROUTER_API_KEY';
|
|
420
|
+
await (0, promises_1.writeFile)(node_path_1.default.join(projectPath, '.env.example'), [
|
|
421
|
+
`${keyEnv}=`,
|
|
422
|
+
'DATABASE_URL=postgresql://postgres:postgres@localhost:5432/siduri',
|
|
423
|
+
'VTS_URL=ws://127.0.0.1:8001',
|
|
424
|
+
'VTS_AUTH_TOKEN=',
|
|
425
|
+
'',
|
|
426
|
+
].join('\n'), { mode: 0o600 });
|
|
427
|
+
await withTask('Installing Siduri runtime dependencies', () => execFile('npm', ['install', '--no-audit', '--no-fund'], { cwd: projectPath }).then(() => undefined));
|
|
428
|
+
printSuccess(`Siduri instance ready · ${projectPath}`);
|
|
429
|
+
console.log(`${colors.dim}Next: cd ${projectDirectoryName(answers.name)} && npm run start${colors.reset}\n`);
|
|
339
430
|
}
|
|
340
431
|
main().catch((error) => {
|
|
341
432
|
if (error && typeof error === 'object' && 'name' in error && error.name === 'ExitPromptError') {
|