@vxnus/siduri 0.0.1 → 0.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.
- package/README.md +30 -1
- package/dist/index.js +77 -5
- package/dist/runtime.js +1523 -0
- package/package.json +10 -4
package/README.md
CHANGED
|
@@ -2,12 +2,41 @@
|
|
|
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.2 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
|
+
The wizard creates a project directory from the companion name, writes
|
|
25
|
+
`siduri.config.json`, copies the Siduri runtime, and installs the runtime
|
|
26
|
+
dependencies. API keys are never written to the configuration file. Optional
|
|
27
|
+
organs can be configured as `{ "provider": "none" }`; Brain and Memory remain
|
|
28
|
+
required.
|
|
29
|
+
|
|
30
|
+
After setup, start the generated instance with:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
cd ganyu
|
|
34
|
+
npm run start
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
For local development, build the CLI from the repository root with
|
|
38
|
+
`pnpm --filter @vxnus/siduri build`. For the full architecture, see the
|
|
39
|
+
[CLI documentation](../docs/cli.md) and
|
|
40
|
+
[configuration reference](../docs/configuration.md).
|
|
41
|
+
|
|
13
42
|
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.2';
|
|
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.2${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
|
}
|
|
@@ -244,7 +296,9 @@ async function main() {
|
|
|
244
296
|
{ type: 'input', name: 'name', message: 'Companion name:', default: 'Siduri', validate: nonEmpty },
|
|
245
297
|
{ type: 'list', name: 'memory', message: 'Memory provider?', choices: [{ name: 'PostgreSQL', value: 'postgres' }] },
|
|
246
298
|
]);
|
|
247
|
-
|
|
299
|
+
const projectPath = node_path_1.default.resolve(process.cwd(), projectDirectoryName(answers.name));
|
|
300
|
+
await (0, promises_1.mkdir)(projectPath, { recursive: true });
|
|
301
|
+
printSuccess(`${answers.name} · PostgreSQL memory · ${projectPath}`);
|
|
248
302
|
printSection('Brain · required');
|
|
249
303
|
const { brainProvider } = await inquirer_1.default.prompt({
|
|
250
304
|
type: 'list',
|
|
@@ -297,7 +351,7 @@ async function main() {
|
|
|
297
351
|
body: { provider: remaining.body, vtsUrl: process.env.VTS_URL || 'ws://127.0.0.1:8001' },
|
|
298
352
|
vision: { provider: remaining.vision, model: 'gpt-4-vision' },
|
|
299
353
|
};
|
|
300
|
-
const configPath = node_path_1.default.join(
|
|
354
|
+
const configPath = node_path_1.default.join(projectPath, 'siduri.config.json');
|
|
301
355
|
try {
|
|
302
356
|
await (0, promises_1.readFile)(configPath, 'utf8');
|
|
303
357
|
const { overwrite } = await inquirer_1.default.prompt({
|
|
@@ -335,7 +389,25 @@ async function main() {
|
|
|
335
389
|
}
|
|
336
390
|
await (0, promises_1.writeFile)(configPath, JSON.stringify(config, null, 2) + '\n', { mode: 0o600 });
|
|
337
391
|
printSuccess(`Configuration written · ${configPath}`);
|
|
338
|
-
|
|
392
|
+
await (0, promises_1.cp)(node_path_1.default.join(__dirname, 'runtime.js'), node_path_1.default.join(projectPath, 'siduri-runtime.js'));
|
|
393
|
+
await (0, promises_1.writeFile)(node_path_1.default.join(projectPath, 'package.json'), JSON.stringify({
|
|
394
|
+
name: projectDirectoryName(answers.name),
|
|
395
|
+
private: true,
|
|
396
|
+
version: '0.0.0',
|
|
397
|
+
scripts: { start: 'node siduri-runtime.js', dev: 'node siduri-runtime.js' },
|
|
398
|
+
dependencies: RUNTIME_DEPENDENCIES,
|
|
399
|
+
}, null, 2) + '\n', { mode: 0o600 });
|
|
400
|
+
const keyEnv = config.brain.apiKeyEnv || 'OPENROUTER_API_KEY';
|
|
401
|
+
await (0, promises_1.writeFile)(node_path_1.default.join(projectPath, '.env.example'), [
|
|
402
|
+
`${keyEnv}=`,
|
|
403
|
+
'DATABASE_URL=postgresql://postgres:postgres@localhost:5432/siduri',
|
|
404
|
+
'VTS_URL=ws://127.0.0.1:8001',
|
|
405
|
+
'VTS_AUTH_TOKEN=',
|
|
406
|
+
'',
|
|
407
|
+
].join('\n'), { mode: 0o600 });
|
|
408
|
+
await withTask('Installing Siduri runtime dependencies', () => execFile('npm', ['install', '--no-audit', '--no-fund'], { cwd: projectPath }).then(() => undefined));
|
|
409
|
+
printSuccess(`Siduri instance ready · ${projectPath}`);
|
|
410
|
+
console.log(`${colors.dim}Next: cd ${projectDirectoryName(answers.name)} && npm run start${colors.reset}\n`);
|
|
339
411
|
}
|
|
340
412
|
main().catch((error) => {
|
|
341
413
|
if (error && typeof error === 'object' && 'name' in error && error.name === 'ExitPromptError') {
|