@vxnus/siduri 0.1.7 → 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/chunks/0bncolc2nuzmo.css +0 -1
  64. package/dist/web-dist/_next/static/chunks/0cz1d0mv5g_q7.js +0 -1
  65. package/dist/web-dist/_next/static/chunks/0uwih7sydv413.js +0 -1
  66. package/dist/web-dist/_next/static/chunks/0xe6aaej0xsj8.js +0 -30
  67. package/dist/web-dist/_next/static/chunks/10rmct1ax-opq.js +0 -1
  68. package/dist/web-dist/_next/static/chunks/1_yae15ffa5f6.js +0 -1
  69. package/dist/web-dist/_next/static/chunks/2kcqevsmv6kh2.js +0 -31
  70. package/dist/web-dist/_next/static/chunks/2s3d1bfr0l4b0.js +0 -1
  71. package/dist/web-dist/_next/static/chunks/32z87id9k6i2z.js +0 -22
  72. package/dist/web-dist/_next/static/chunks/3bx2gs3idjmo1.js +0 -1
  73. package/dist/web-dist/_next/static/chunks/turbopack-3eipe4c-imn5l.js +0 -1
  74. package/dist/web-dist/_next/static/media/favicon.2vob68tjqpejf.ico +0 -0
  75. package/dist/web-dist/_next/static/uvsK8ULhL7fHQMR8sr_JL/_buildManifest.js +0 -11
  76. package/dist/web-dist/_next/static/uvsK8ULhL7fHQMR8sr_JL/_clientMiddlewareManifest.js +0 -1
  77. package/dist/web-dist/_next/static/uvsK8ULhL7fHQMR8sr_JL/_ssgManifest.js +0 -1
  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
@@ -1,197 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const generator_1 = require("./generator");
4
- describe('Instance Generator Composition Invariants (Phase 3)', () => {
5
- const MOCK_MANIFESTS = {
6
- brain: {
7
- name: '@siduri-x/brain',
8
- organType: 'brain',
9
- version: '1.0.0',
10
- displayName: 'Brain (Cognition & Planning)',
11
- entrypoint: './dist/index.js',
12
- factory: 'OpenRouterBrain',
13
- configKey: 'brain',
14
- configSchema: { type: 'object', properties: { provider: { type: 'string' }, model: { type: 'string' } } },
15
- environment: [{ name: 'OPENROUTER_API_KEY', required: true, secret: true }],
16
- services: [{ name: 'LLM Inference', kind: 'http_service' }],
17
- },
18
- hands: {
19
- name: '@siduri-x/hands',
20
- organType: 'hands',
21
- version: '1.0.0',
22
- displayName: 'Hands (MCP Tool Execution)',
23
- entrypoint: './dist/index.js',
24
- factory: 'DefaultHandsOrgan',
25
- configKey: 'hands',
26
- configSchema: { type: 'object', properties: { defaultTimeoutMs: { type: 'number' } } },
27
- environment: [{ name: 'ACTION_POLICY_SECRET', required: true, secret: true }],
28
- services: [],
29
- },
30
- memory: {
31
- name: '@siduri-x/memory',
32
- organType: 'memory',
33
- version: '1.0.0',
34
- displayName: 'Memory (PostgreSQL FTS Claims)',
35
- entrypoint: './dist/index.js',
36
- factory: 'PostgresMemoryOrgan',
37
- configKey: 'memory',
38
- configSchema: { type: 'object', properties: { provider: { type: 'string' } } },
39
- environment: [{ name: 'DATABASE_URL', required: true, secret: true }],
40
- services: [{ name: 'PostgreSQL', kind: 'database' }],
41
- database: { engine: 'postgres', migrationsDir: './migrations' },
42
- },
43
- body: {
44
- name: '@siduri-x/body',
45
- organType: 'body',
46
- version: '1.0.0',
47
- displayName: 'Body (Live2D & Avatar State)',
48
- entrypoint: './dist/index.js',
49
- factory: 'NeutralBodyOrgan',
50
- configKey: 'body',
51
- configSchema: { type: 'object', properties: { provider: { type: 'string' } } },
52
- environment: [],
53
- services: [],
54
- },
55
- voice: {
56
- name: '@siduri-x/voice',
57
- organType: 'voice',
58
- version: '1.0.0',
59
- displayName: 'Voice (VOICEVOX Speech Synthesis)',
60
- entrypoint: './dist/index.js',
61
- factory: 'VoiceAdapter',
62
- configKey: 'voice',
63
- configSchema: { type: 'object', properties: { provider: { type: 'string' } } },
64
- environment: [{ name: 'VOICEVOX_URL', default: 'http://localhost:50021' }],
65
- services: [{ name: 'VOICEVOX', kind: 'http_service' }],
66
- },
67
- };
68
- test('Composition A: Brain only', () => {
69
- const files = (0, generator_1.generateInstanceFiles)({
70
- name: 'brain-only-agent',
71
- selectedManifests: [MOCK_MANIFESTS.brain],
72
- });
73
- const pkg = JSON.parse(files['package.json']);
74
- expect(pkg.dependencies['@siduri-x/core']).toBeDefined();
75
- expect(pkg.dependencies['@siduri-x/brain']).toBeDefined();
76
- expect(pkg.dependencies['@siduri-x/memory']).toBeUndefined();
77
- expect(pkg.dependencies['@siduri-x/hands']).toBeUndefined();
78
- expect(pkg.dependencies['@siduri-x/voice']).toBeUndefined();
79
- expect(pkg.dependencies['@siduri-x/body']).toBeUndefined();
80
- // src/index.js
81
- expect(files['src/index.js']).toContain("import { OpenRouterBrain } from '@siduri-x/brain'");
82
- expect(files['src/index.js']).not.toContain('@siduri-x/hands');
83
- expect(files['src/index.js']).not.toContain('@siduri-x/memory');
84
- expect(files['src/index.js']).not.toContain('siduri-runtime.js');
85
- // siduri.config.json
86
- const config = JSON.parse(files['siduri.config.json']);
87
- expect(config.organs.brain).toBeDefined();
88
- expect(config.organs.hands).toBeUndefined();
89
- expect(config.organs.memory).toBeUndefined();
90
- // .env.example
91
- expect(files['.env.example']).toContain('OPENROUTER_API_KEY');
92
- expect(files['.env.example']).not.toContain('DATABASE_URL');
93
- expect(files['.env.example']).not.toContain('ACTION_POLICY_SECRET');
94
- // No body asset scaffold
95
- expect(files.createAssetsBodyDir).toBe(false);
96
- });
97
- test('Composition B: Brain + Hands', () => {
98
- const files = (0, generator_1.generateInstanceFiles)({
99
- name: 'coding-agent',
100
- selectedManifests: [MOCK_MANIFESTS.brain, MOCK_MANIFESTS.hands],
101
- });
102
- const pkg = JSON.parse(files['package.json']);
103
- expect(pkg.dependencies['@siduri-x/core']).toBeDefined();
104
- expect(pkg.dependencies['@siduri-x/brain']).toBeDefined();
105
- expect(pkg.dependencies['@siduri-x/hands']).toBeDefined();
106
- expect(pkg.dependencies['@siduri-x/memory']).toBeUndefined();
107
- // src/index.js
108
- expect(files['src/index.js']).toContain("import { OpenRouterBrain } from '@siduri-x/brain'");
109
- expect(files['src/index.js']).toContain("import { DefaultHandsOrgan } from '@siduri-x/hands'");
110
- expect(files['src/index.js']).not.toContain('@siduri-x/memory');
111
- // .env.example
112
- expect(files['.env.example']).toContain('OPENROUTER_API_KEY');
113
- expect(files['.env.example']).toContain('ACTION_POLICY_SECRET');
114
- expect(files['.env.example']).not.toContain('DATABASE_URL');
115
- expect(files.createAssetsBodyDir).toBe(false);
116
- });
117
- test('Composition C: Brain + Memory', () => {
118
- const files = (0, generator_1.generateInstanceFiles)({
119
- name: 'memory-agent',
120
- selectedManifests: [MOCK_MANIFESTS.brain, MOCK_MANIFESTS.memory],
121
- });
122
- const pkg = JSON.parse(files['package.json']);
123
- expect(pkg.dependencies['@siduri-x/core']).toBeDefined();
124
- expect(pkg.dependencies['@siduri-x/brain']).toBeDefined();
125
- expect(pkg.dependencies['@siduri-x/memory']).toBeDefined();
126
- expect(pkg.dependencies['@siduri-x/hands']).toBeUndefined();
127
- // .env.example
128
- expect(files['.env.example']).toContain('OPENROUTER_API_KEY');
129
- expect(files['.env.example']).toContain('DATABASE_URL');
130
- expect(files['.env.example']).not.toContain('ACTION_POLICY_SECRET');
131
- // README mentions database
132
- expect(files['README.md']).toContain('DATABASE_URL');
133
- expect(files['README.md']).toContain('npx @vxnus/siduri db push');
134
- });
135
- test('Composition D: Full with Body', () => {
136
- const files = (0, generator_1.generateInstanceFiles)({
137
- name: 'companion-full',
138
- selectedManifests: [
139
- MOCK_MANIFESTS.brain,
140
- MOCK_MANIFESTS.memory,
141
- MOCK_MANIFESTS.hands,
142
- MOCK_MANIFESTS.body,
143
- MOCK_MANIFESTS.voice,
144
- ],
145
- });
146
- const pkg = JSON.parse(files['package.json']);
147
- expect(pkg.dependencies['@siduri-x/core']).toBeDefined();
148
- expect(pkg.dependencies['@siduri-x/brain']).toBeDefined();
149
- expect(pkg.dependencies['@siduri-x/memory']).toBeDefined();
150
- expect(pkg.dependencies['@siduri-x/hands']).toBeDefined();
151
- expect(pkg.dependencies['@siduri-x/body']).toBeDefined();
152
- expect(pkg.dependencies['@siduri-x/voice']).toBeDefined();
153
- // Body & voice asset directories requested
154
- expect(files.createAssetsBodyDir).toBe(true);
155
- expect(files.createAssetsDirs).toContain('assets/body/companion-full');
156
- expect(files.createAssetsDirs).toContain('assets/voice/companion-full');
157
- // README mentions Live2D model assets & prerequisites
158
- expect(files['README.md']).toContain('assets/body/companion-full');
159
- expect(files['README.md']).toContain('assets/voice/companion-full');
160
- expect(files['README.md']).toContain('Prerequisites');
161
- // Docker compose generated for memory (voicevox is auto-downloaded at runtime)
162
- expect(files['docker-compose.yml']).toBeDefined();
163
- expect(files['docker-compose.yml']).toContain('postgres:15');
164
- expect(files['README.md']).toContain('Voicevox engine executable will be securely auto-downloaded');
165
- expect(pkg.scripts['services:up']).toBe('docker compose up -d');
166
- expect(pkg.scripts['services:down']).toBe('docker compose down');
167
- });
168
- test('Composition E: Brain only has no docker-compose.yml', () => {
169
- const files = (0, generator_1.generateInstanceFiles)({
170
- name: 'brain-solo',
171
- selectedManifests: [MOCK_MANIFESTS.brain],
172
- });
173
- expect(files['docker-compose.yml']).toBeUndefined();
174
- const pkg = JSON.parse(files['package.json']);
175
- expect(pkg.scripts['services:up']).toBeUndefined();
176
- expect(files['public/index.html']).toBeDefined();
177
- expect(files['public/index.html']).toContain('Memory Console');
178
- expect(files['public/index.html']).toContain('Companion Chat');
179
- });
180
- test('Generated runtime server template enforces loopback binding, safe health, and path containment', () => {
181
- const files = (0, generator_1.generateInstanceFiles)({
182
- name: 'secure-companion',
183
- selectedManifests: [MOCK_MANIFESTS.brain, MOCK_MANIFESTS.memory],
184
- });
185
- const srcIndexJs = files['src/index.js'];
186
- // 1. Explicit loopback binding 127.0.0.1
187
- expect(srcIndexJs).toContain("server.listen(Number(PORT), '127.0.0.1'");
188
- expect(srcIndexJs).toContain("http://127.0.0.1:");
189
- // 2. Minimal /health endpoint without config.organs or secrets
190
- expect(srcIndexJs).toContain("pathname === '/health'");
191
- expect(srcIndexJs).not.toContain('organs: config.organs');
192
- // 3. Strict path traversal containment
193
- expect(srcIndexJs).toContain('relative.startsWith(\'..\')');
194
- expect(srcIndexJs).toContain('path.isAbsolute(relative)');
195
- expect(srcIndexJs).toContain('decodeURIComponent');
196
- });
197
- });
package/dist/index.d.ts DELETED
@@ -1,20 +0,0 @@
1
- #!/usr/bin/env node
2
- import { OrganManifest } from './manifest';
3
- export declare const CLI_VERSION = "0.1.7";
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>;
18
- export declare function runCreateWizard(targetDir?: string): Promise<void>;
19
- export declare function runCliDoctor(targetDir?: string): Promise<void>;
20
- export declare function runCliDb(subcommand?: string, targetDir?: string): Promise<void>;
package/dist/index.js DELETED
@@ -1,401 +0,0 @@
1
- #!/usr/bin/env node
2
- "use strict";
3
- var __importDefault = (this && this.__importDefault) || function (mod) {
4
- return (mod && mod.__esModule) ? mod : { "default": mod };
5
- };
6
- Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.colors = exports.CLI_VERSION = void 0;
8
- exports.printHeader = printHeader;
9
- exports.printSection = printSection;
10
- exports.printSuccess = printSuccess;
11
- exports.projectDirectoryName = projectDirectoryName;
12
- exports.formatReviewSummary = formatReviewSummary;
13
- exports.withTask = withTask;
14
- exports.runCreateWizard = runCreateWizard;
15
- exports.runCliDoctor = runCliDoctor;
16
- exports.runCliDb = runCliDb;
17
- const node_child_process_1 = require("node:child_process");
18
- const node_fs_1 = __importDefault(require("node:fs"));
19
- const promises_1 = require("node:fs/promises");
20
- const node_path_1 = __importDefault(require("node:path"));
21
- const node_util_1 = require("node:util");
22
- const inquirer_1 = __importDefault(require("inquirer"));
23
- const discovery_1 = require("./discovery");
24
- const generator_1 = require("./generator");
25
- const doctor_1 = require("./doctor");
26
- const db_1 = require("./db");
27
- const configurators_1 = require("./configurators");
28
- const execFile = (0, node_util_1.promisify)(node_child_process_1.execFile);
29
- exports.CLI_VERSION = '0.1.7';
30
- exports.colors = {
31
- cyan: '\u001b[36m',
32
- dim: '\u001b[2m',
33
- green: '\u001b[32m',
34
- yellow: '\u001b[33m',
35
- bold: '\u001b[1m',
36
- reset: '\u001b[0m',
37
- };
38
- function printHeader() {
39
- console.log(`\n${exports.colors.cyan}◈ SIDURI${exports.colors.reset} ${exports.colors.dim}companion setup (manifest-driven)${exports.colors.reset}`);
40
- console.log(`${exports.colors.yellow}Version ${exports.CLI_VERSION}${exports.colors.reset} · composable standalone architecture\n`);
41
- }
42
- function printSection(title) {
43
- console.log(`\n${exports.colors.cyan}── ${title} ${'─'.repeat(Math.max(2, 42 - title.length))}${exports.colors.reset}\n`);
44
- }
45
- function printSuccess(message) {
46
- console.log(`${exports.colors.green}✓${exports.colors.reset} ${message}`);
47
- }
48
- function projectDirectoryName(value) {
49
- const slug = value
50
- .trim()
51
- .toLowerCase()
52
- .replace(/[^a-z0-9]+/g, '-')
53
- .replace(/^-+|-+$/g, '');
54
- return slug || 'siduri';
55
- }
56
- function formatReviewSummary(companionName, selectedManifests, organSummaries) {
57
- const lines = [];
58
- lines.push(`\n${exports.colors.cyan}── Review ${companionName} ${'─'.repeat(Math.max(2, 42 - (companionName.length + 9)))}${exports.colors.reset}\n`);
59
- lines.push(` ${exports.colors.bold}Companion${exports.colors.reset}`);
60
- lines.push(` ${exports.colors.dim}Name:${exports.colors.reset} ${companionName}\n`);
61
- for (const m of selectedManifests) {
62
- const isRequired = m.organType === 'brain';
63
- const tag = isRequired ? ` ${exports.colors.dim}· required${exports.colors.reset}` : '';
64
- lines.push(` ${exports.colors.bold}${m.displayName.split(' ')[0] || m.organType}${exports.colors.reset}${tag}`);
65
- const summary = organSummaries[m.configKey] || organSummaries[m.organType] || {};
66
- const entries = Object.entries(summary);
67
- if (entries.length === 0) {
68
- lines.push(` ${exports.colors.dim}Provider:${exports.colors.reset} ${m.displayName}`);
69
- }
70
- else {
71
- for (const [key, val] of entries) {
72
- const valStr = String(val);
73
- lines.push(` ${exports.colors.dim}${key}:${exports.colors.reset}${' '.repeat(Math.max(1, 10 - key.length))}${valStr}`);
74
- }
75
- }
76
- lines.push('');
77
- }
78
- lines.push(`${exports.colors.cyan}${'─'.repeat(46)}${exports.colors.reset}\n`);
79
- return lines.join('\n');
80
- }
81
- async function withTask(label, task) {
82
- process.stdout.write(`${exports.colors.dim}${label}${exports.colors.reset}`);
83
- const frames = ['·', '•', '●', '•'];
84
- let index = 0;
85
- const timer = setInterval(() => {
86
- process.stdout.write(`\r${exports.colors.dim}${label} ${frames[index++ % frames.length]}${exports.colors.reset}`);
87
- }, 120);
88
- try {
89
- const result = await task();
90
- clearInterval(timer);
91
- process.stdout.write(`\r${exports.colors.green}✓${exports.colors.reset} ${label}\n`);
92
- return result;
93
- }
94
- catch (error) {
95
- clearInterval(timer);
96
- process.stdout.write(`\r${exports.colors.yellow}!${exports.colors.reset} ${label}\n`);
97
- throw error;
98
- }
99
- }
100
- function nonEmpty(value) {
101
- return value.trim().length > 0 || 'Please enter a value.';
102
- }
103
- async function runCreateWizard(targetDir) {
104
- printHeader();
105
- // 1. Discover manifests from installed or monorepo packages
106
- const registry = discovery_1.OrganRegistry.discover();
107
- const availableManifests = registry.getAll();
108
- if (availableManifests.length === 0) {
109
- throw new Error('No @siduri-x/* organ packages found. Please ensure organs are installed or in workspace.');
110
- }
111
- printSection('Companion Details');
112
- const basicAnswers = await inquirer_1.default.prompt([
113
- {
114
- type: 'input',
115
- name: 'name',
116
- message: 'Companion name:',
117
- default: 'Siduri',
118
- validate: nonEmpty,
119
- },
120
- ]);
121
- const companionName = basicAnswers.name;
122
- const projectDir = targetDir ? node_path_1.default.resolve(process.cwd(), targetDir) : node_path_1.default.resolve(process.cwd(), projectDirectoryName(companionName));
123
- printSection('Organ Selection');
124
- console.log(`${exports.colors.dim}Select any combination of organs to compose into your standalone instance.${exports.colors.reset}\n`);
125
- // Brain is required by architecture contract for cognition
126
- const brainManifest = registry.get('brain');
127
- const nonBrainManifests = availableManifests.filter((m) => m.organType !== 'brain');
128
- const organChoices = nonBrainManifests.map((m) => ({
129
- name: `${m.displayName} (${m.name})`,
130
- value: m.organType,
131
- checked: m.organType === 'memory', // default memory checked
132
- }));
133
- const { selectedOrganTypes } = await inquirer_1.default.prompt({
134
- type: 'checkbox',
135
- name: 'selectedOrganTypes',
136
- message: 'Select organs to install:',
137
- choices: organChoices,
138
- });
139
- const selectedManifests = [];
140
- if (brainManifest) {
141
- selectedManifests.push(brainManifest);
142
- }
143
- for (const organType of selectedOrganTypes) {
144
- const m = registry.get(organType);
145
- if (m)
146
- selectedManifests.push(m);
147
- }
148
- // 2. Interactive Organ Configuration Stage
149
- const organConfigs = {};
150
- const organSummaries = {};
151
- for (const m of selectedManifests) {
152
- const isRequired = m.organType === 'brain';
153
- const sectionTitle = isRequired ? `${m.displayName.split(' ')[0] || m.organType} · required` : m.displayName.split(' ')[0] || m.organType;
154
- printSection(sectionTitle);
155
- const res = await (0, configurators_1.configureOrgan)(m, {
156
- companionName,
157
- existingConfig: organConfigs[m.configKey],
158
- });
159
- organConfigs[m.configKey] = res.config;
160
- organSummaries[m.configKey] = res.summary || {};
161
- }
162
- // 3. Final Review and Edit Loop
163
- while (true) {
164
- console.log(formatReviewSummary(companionName, selectedManifests, organSummaries));
165
- const { reviewAction } = await inquirer_1.default.prompt({
166
- type: 'list',
167
- name: 'reviewAction',
168
- message: `Create ${companionName} with this configuration?`,
169
- choices: [
170
- { name: 'Yes, create', value: 'create' },
171
- { name: 'Go back and edit', value: 'edit' },
172
- { name: 'Cancel', value: 'cancel' },
173
- ],
174
- });
175
- if (reviewAction === 'cancel') {
176
- console.log('Instance creation cancelled.');
177
- return;
178
- }
179
- if (reviewAction === 'create') {
180
- break;
181
- }
182
- if (reviewAction === 'edit') {
183
- const editChoices = selectedManifests.map((m) => ({
184
- name: `Edit ${m.displayName}`,
185
- value: m.configKey,
186
- }));
187
- editChoices.push({ name: 'Edit all organs in sequence', value: '__ALL__' });
188
- editChoices.push({ name: 'Back to review', value: '__BACK__' });
189
- const { organToEdit } = await inquirer_1.default.prompt({
190
- type: 'list',
191
- name: 'organToEdit',
192
- message: 'Which organ would you like to edit?',
193
- choices: editChoices,
194
- });
195
- if (organToEdit === '__BACK__') {
196
- continue;
197
- }
198
- const organsToReconfigure = organToEdit === '__ALL__'
199
- ? selectedManifests
200
- : selectedManifests.filter((m) => m.configKey === organToEdit);
201
- for (const m of organsToReconfigure) {
202
- const isRequired = m.organType === 'brain';
203
- const sectionTitle = isRequired ? `${m.displayName.split(' ')[0] || m.organType} · required` : m.displayName.split(' ')[0] || m.organType;
204
- printSection(sectionTitle);
205
- const res = await (0, configurators_1.configureOrgan)(m, {
206
- companionName,
207
- existingConfig: organConfigs[m.configKey],
208
- });
209
- organConfigs[m.configKey] = res.config;
210
- organSummaries[m.configKey] = res.summary || {};
211
- }
212
- }
213
- }
214
- // 4. Generate Instance Files
215
- const files = (0, generator_1.generateInstanceFiles)({
216
- name: companionName,
217
- selectedManifests,
218
- organConfigs,
219
- });
220
- await (0, promises_1.mkdir)(projectDir, { recursive: true });
221
- await (0, promises_1.mkdir)(node_path_1.default.join(projectDir, 'src'), { recursive: true });
222
- const publicDir = node_path_1.default.join(projectDir, 'public');
223
- await (0, promises_1.mkdir)(publicDir, { recursive: true });
224
- await (0, promises_1.writeFile)(node_path_1.default.join(projectDir, 'package.json'), files['package.json'], 'utf8');
225
- await (0, promises_1.writeFile)(node_path_1.default.join(projectDir, 'siduri.config.json'), files['siduri.config.json'], 'utf8');
226
- await (0, promises_1.writeFile)(node_path_1.default.join(projectDir, 'siduri.schema.json'), files['siduri.schema.json'], 'utf8');
227
- await (0, promises_1.writeFile)(node_path_1.default.join(projectDir, '.env.example'), files['.env.example'], 'utf8');
228
- await (0, promises_1.writeFile)(node_path_1.default.join(projectDir, 'README.md'), files['README.md'], 'utf8');
229
- await (0, promises_1.writeFile)(node_path_1.default.join(projectDir, 'src/index.js'), files['src/index.js'], 'utf8');
230
- // Copy full Next.js apps/web production build if present
231
- const webDistCandidates = [
232
- node_path_1.default.resolve(__dirname, 'web-dist'),
233
- node_path_1.default.resolve(__dirname, '../dist/web-dist'),
234
- node_path_1.default.resolve(__dirname, '../../apps/web/out'),
235
- node_path_1.default.resolve(process.cwd(), 'apps/web/out'),
236
- ];
237
- const foundWebDist = webDistCandidates.find((p) => node_fs_1.default.existsSync(p));
238
- if (foundWebDist) {
239
- node_fs_1.default.cpSync(foundWebDist, publicDir, { recursive: true });
240
- }
241
- else {
242
- await (0, promises_1.writeFile)(node_path_1.default.join(publicDir, 'index.html'), files['public/index.html'], 'utf8');
243
- }
244
- if (files['docker-compose.yml']) {
245
- await (0, promises_1.writeFile)(node_path_1.default.join(projectDir, 'docker-compose.yml'), files['docker-compose.yml'], 'utf8');
246
- }
247
- if (files.createAssetsDirs && files.createAssetsDirs.length > 0) {
248
- for (const dir of files.createAssetsDirs) {
249
- await (0, promises_1.mkdir)(node_path_1.default.join(projectDir, dir), { recursive: true });
250
- }
251
- }
252
- else if (files.createAssetsBodyDir) {
253
- await (0, promises_1.mkdir)(node_path_1.default.join(projectDir, 'assets/body'), { recursive: true });
254
- }
255
- printSuccess(`Generated standalone files at ${projectDir}`);
256
- // 5. Install dependencies from registry
257
- try {
258
- await withTask('Installing dependencies (npm install)', async () => {
259
- await execFile('npm', ['install', '--no-audit', '--no-fund'], { cwd: projectDir });
260
- });
261
- printSuccess('Dependencies installed successfully.');
262
- }
263
- catch (err) {
264
- console.warn(`${exports.colors.yellow}!${exports.colors.reset} Notice: npm install had warnings or requires network: ${err.message}`);
265
- }
266
- printSection('Instance Ready');
267
- console.log(`Your Siduri companion is ready! Next steps:\n`);
268
- console.log(` cd ${node_path_1.default.relative(process.cwd(), projectDir) || '.'}`);
269
- console.log(` cp .env.example .env ${exports.colors.dim}# Fill in required API keys/credentials${exports.colors.reset}`);
270
- if (files['docker-compose.yml']) {
271
- console.log(` npm run services:up ${exports.colors.dim}# Start local Docker services (PostgreSQL / VOICEVOX)${exports.colors.reset}`);
272
- }
273
- const hasMemory = selectedManifests.some((m) => m.organType === 'memory');
274
- if (hasMemory) {
275
- console.log(` npx @vxnus/siduri db push ${exports.colors.dim}# Push PostgreSQL memory schema${exports.colors.reset}`);
276
- }
277
- console.log(` npm run doctor ${exports.colors.dim}# Run diagnostic health probes${exports.colors.reset}`);
278
- console.log(` npm start ${exports.colors.dim}# Start Web Companion & Memory Console at http://localhost:3000${exports.colors.reset}\n`);
279
- }
280
- async function runCliDoctor(targetDir) {
281
- printHeader();
282
- const dir = targetDir ? node_path_1.default.resolve(process.cwd(), targetDir) : process.cwd();
283
- console.log(`${exports.colors.cyan}Siduri Doctor${exports.colors.reset}`);
284
- console.log(`${exports.colors.dim}─────────────${exports.colors.reset}\n`);
285
- try {
286
- const report = await (0, doctor_1.runDoctor)({ projectDir: dir });
287
- console.log(`${exports.colors.dim}Instance:${exports.colors.reset} ${report.instanceName}`);
288
- console.log(`${exports.colors.dim}Organs:${exports.colors.reset} ${report.configuredOrgans.join(', ')}\n`);
289
- const categories = ['Environment', 'Services', 'Database', 'Health Probe'];
290
- for (const cat of categories) {
291
- const items = report.results.filter((r) => r.category === cat);
292
- if (items.length > 0) {
293
- console.log(`${exports.colors.cyan}${cat}${exports.colors.reset}`);
294
- for (const item of items) {
295
- if (item.status === 'PASS') {
296
- console.log(` ${exports.colors.green}✓${exports.colors.reset} ${item.name} ${exports.colors.dim}(${item.message || 'OK'})${exports.colors.reset}`);
297
- }
298
- else if (item.status === 'OPTIONAL_MISSING') {
299
- console.log(` ${exports.colors.dim}○${exports.colors.reset} ${item.name} ${exports.colors.dim}(Optional, not set)${exports.colors.reset}`);
300
- }
301
- else if (item.status === 'SKIPPED') {
302
- console.log(` ${exports.colors.dim}— ${item.name} (${item.message})${exports.colors.reset}`);
303
- }
304
- else {
305
- console.log(` ${exports.colors.yellow}✗${exports.colors.reset} ${item.name}`);
306
- if (item.organName) {
307
- console.log(` ${exports.colors.dim}Required by:${exports.colors.reset} ${item.organName}`);
308
- }
309
- if (item.message) {
310
- console.log(` ${exports.colors.yellow}${item.message}${exports.colors.reset}`);
311
- }
312
- if (item.remediation) {
313
- console.log(` ${exports.colors.dim}Remediation:${exports.colors.reset} ${item.remediation}`);
314
- }
315
- }
316
- }
317
- console.log();
318
- }
319
- }
320
- if (report.passed) {
321
- console.log(`${exports.colors.green}Result: PASS${exports.colors.reset}\n`);
322
- process.exitCode = 0;
323
- }
324
- else {
325
- console.log(`${exports.colors.yellow}Result: FAIL${exports.colors.reset}\n`);
326
- process.exitCode = 1;
327
- }
328
- }
329
- catch (err) {
330
- console.error(`\n${exports.colors.yellow}Doctor Error:${exports.colors.reset} ${err.message}\n`);
331
- process.exitCode = 2;
332
- }
333
- }
334
- async function runCliDb(subcommand, targetDir) {
335
- printHeader();
336
- if (subcommand !== 'push') {
337
- console.log('Usage: siduri db push');
338
- process.exitCode = 2;
339
- return;
340
- }
341
- const dir = targetDir ? node_path_1.default.resolve(process.cwd(), targetDir) : process.cwd();
342
- console.log(`${exports.colors.cyan}Siduri Database Migrations${exports.colors.reset}`);
343
- console.log(`${exports.colors.dim}──────────────────────────${exports.colors.reset}\n`);
344
- try {
345
- const res = await (0, db_1.runDbPush)({ projectDir: dir });
346
- if (res.status === 'NOOP') {
347
- console.log(`${exports.colors.dim}— ${res.message}${exports.colors.reset}\n`);
348
- }
349
- else {
350
- printSuccess(res.message);
351
- if (res.appliedMigrations.length > 0) {
352
- console.log(`${exports.colors.dim}Applied:${exports.colors.reset} ${res.appliedMigrations.join(', ')}`);
353
- }
354
- console.log();
355
- }
356
- process.exitCode = 0;
357
- }
358
- catch (err) {
359
- console.error(`\n${exports.colors.yellow}Database Migration Error:${exports.colors.reset} ${err.message}\n`);
360
- process.exitCode = 3;
361
- }
362
- }
363
- async function main() {
364
- const args = process.argv.slice(2);
365
- const command = args[0];
366
- if (command === '--version' || command === '-v') {
367
- console.log(exports.CLI_VERSION);
368
- return;
369
- }
370
- if (command === 'create') {
371
- const targetDir = args[1];
372
- await runCreateWizard(targetDir);
373
- return;
374
- }
375
- if (command === 'doctor') {
376
- const targetDir = args[1];
377
- await runCliDoctor(targetDir);
378
- return;
379
- }
380
- if (command === 'db') {
381
- const subcommand = args[1];
382
- const targetDir = args[2];
383
- await runCliDb(subcommand, targetDir);
384
- return;
385
- }
386
- printHeader();
387
- console.log('Usage: npx @vxnus/siduri create [directory]');
388
- console.log(' npx @vxnus/siduri doctor [directory]');
389
- console.log(' npx @vxnus/siduri db push [directory]');
390
- console.log(' npx @vxnus/siduri --version\n');
391
- }
392
- if (require.main === module) {
393
- main().catch((error) => {
394
- if (error && typeof error === 'object' && 'name' in error && error.name === 'ExitPromptError') {
395
- console.log('\nOperation cancelled.');
396
- return;
397
- }
398
- console.error(`\n${exports.colors.yellow}!${exports.colors.reset} ${error instanceof Error ? error.message : error}`);
399
- process.exitCode = 1;
400
- });
401
- }
@@ -1,33 +0,0 @@
1
- export interface OrganEnvironmentVar {
2
- name: string;
3
- required?: boolean;
4
- secret?: boolean;
5
- default?: string;
6
- description?: string;
7
- }
8
- export interface OrganServiceRequirement {
9
- name: string;
10
- kind: 'database' | 'http_service' | 'process' | string;
11
- optional?: boolean;
12
- description?: string;
13
- }
14
- export interface OrganDatabaseRequirement {
15
- engine: 'postgres' | 'sqlite' | string;
16
- migrationsDir?: string;
17
- }
18
- export interface OrganManifest {
19
- name: string;
20
- organType: string;
21
- version: string;
22
- displayName: string;
23
- description?: string;
24
- entrypoint: string;
25
- factory: string;
26
- configKey: string;
27
- configSchema: Record<string, any>;
28
- environment: OrganEnvironmentVar[];
29
- services: OrganServiceRequirement[];
30
- database?: OrganDatabaseRequirement | null;
31
- healthCheck?: string | null;
32
- }
33
- export declare function validateOrganManifest(manifest: unknown, sourcePath?: string): OrganManifest;