siduri 1.0.0
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/LICENSE +6 -0
- package/README.md +84 -0
- package/dist/builtin-manifests.d.ts +2 -0
- package/dist/builtin-manifests.js +524 -0
- package/dist/clean-machine-e2e.test.d.ts +1 -0
- package/dist/clean-machine-e2e.test.js +160 -0
- package/dist/clean-machine-smoke.test.d.ts +1 -0
- package/dist/clean-machine-smoke.test.js +165 -0
- package/dist/colors.d.ts +8 -0
- package/dist/colors.js +11 -0
- package/dist/configurators/behavior.d.ts +2 -0
- package/dist/configurators/behavior.js +77 -0
- package/dist/configurators/body.d.ts +2 -0
- package/dist/configurators/body.js +107 -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 +43 -0
- package/dist/configurators/hands.d.ts +2 -0
- package/dist/configurators/hands.js +43 -0
- package/dist/configurators/index.d.ts +24 -0
- package/dist/configurators/index.js +78 -0
- package/dist/configurators/knowledge.d.ts +6 -0
- package/dist/configurators/knowledge.js +146 -0
- package/dist/configurators/memory.d.ts +2 -0
- package/dist/configurators/memory.js +26 -0
- package/dist/configurators/mouth.d.ts +2 -0
- package/dist/configurators/mouth.js +35 -0
- package/dist/configurators/observation.d.ts +2 -0
- package/dist/configurators/observation.js +38 -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 +47 -0
- package/dist/configurators/voice.d.ts +2 -0
- package/dist/configurators/voice.js +373 -0
- package/dist/configurators.test.d.ts +1 -0
- package/dist/configurators.test.js +464 -0
- package/dist/db.d.ts +13 -0
- package/dist/db.js +15 -0
- package/dist/discovery.d.ts +13 -0
- package/dist/discovery.js +85 -0
- package/dist/discovery.test.d.ts +1 -0
- package/dist/discovery.test.js +69 -0
- package/dist/doctor-db.test.d.ts +1 -0
- package/dist/doctor-db.test.js +52 -0
- package/dist/doctor.d.ts +19 -0
- package/dist/doctor.js +266 -0
- package/dist/generator.d.ts +23 -0
- package/dist/generator.js +1094 -0
- package/dist/generator.test.d.ts +1 -0
- package/dist/generator.test.js +252 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.js +607 -0
- package/dist/manifest.d.ts +33 -0
- package/dist/manifest.js +40 -0
- package/dist/project-dir.test.d.ts +1 -0
- package/dist/project-dir.test.js +37 -0
- package/dist/providers/knowledge-hub.d.ts +44 -0
- package/dist/providers/knowledge-hub.js +162 -0
- package/dist/providers/openrouter.d.ts +32 -0
- package/dist/providers/openrouter.js +201 -0
- package/dist/release-check.d.ts +9 -0
- package/dist/release-check.js +128 -0
- package/dist/runtime-parity.test.d.ts +1 -0
- package/dist/runtime-parity.test.js +141 -0
- package/dist/schema-validator.d.ts +9 -0
- package/dist/schema-validator.js +107 -0
- 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 +32 -0
- package/dist/web-dist/__next._tree.txt +4 -0
- package/dist/web-dist/_next/static/4aL_iP3FHsLSyHzCnRQYD/_buildManifest.js +1 -0
- package/dist/web-dist/_next/static/4aL_iP3FHsLSyHzCnRQYD/_ssgManifest.js +1 -0
- package/dist/web-dist/_next/static/chunks/136-1d10af93b770a1c8.js +52 -0
- package/dist/web-dist/_next/static/chunks/1629039a.f535b3ff45566416.js +1 -0
- package/dist/web-dist/_next/static/chunks/202.59b8eb8a8c45f711.js +1 -0
- package/dist/web-dist/_next/static/chunks/2be4ccb0.ab2975eb50b4e166.js +1 -0
- package/dist/web-dist/_next/static/chunks/411.d68b2e48424f1e47.js +1 -0
- package/dist/web-dist/_next/static/chunks/426-9f7f6e7fffd4c3c3.js +1 -0
- package/dist/web-dist/_next/static/chunks/563b947f-8e2871a2ab7cd91e.js +1 -0
- package/dist/web-dist/_next/static/chunks/92e71660.11f182d50bce2be0.js +342 -0
- package/dist/web-dist/_next/static/chunks/app/_global-error/page-bce6d30fb2b1a3b0.js +1 -0
- package/dist/web-dist/_next/static/chunks/app/_not-found/page-74658f4988eabcc7.js +1 -0
- package/dist/web-dist/_next/static/chunks/app/chat/page-ab56048b707a3ddd.js +34 -0
- package/dist/web-dist/_next/static/chunks/app/layout-14f1a3f31e58be17.js +1 -0
- package/dist/web-dist/_next/static/chunks/app/operator/page-6b2d0ba884183ad7.js +1 -0
- package/dist/web-dist/_next/static/chunks/app/page-fc4bf56cf33ae27b.js +1 -0
- package/dist/web-dist/_next/static/chunks/framework-7afb7035d9872ea0.js +1 -0
- package/dist/web-dist/_next/static/chunks/main-8553b996986f1210.js +5 -0
- package/dist/web-dist/_next/static/chunks/main-app-9e6a144626e5a5b9.js +1 -0
- package/dist/web-dist/_next/static/chunks/next/dist/client/components/builtin/app-error-bce6d30fb2b1a3b0.js +1 -0
- package/dist/web-dist/_next/static/chunks/next/dist/client/components/builtin/forbidden-bce6d30fb2b1a3b0.js +1 -0
- package/dist/web-dist/_next/static/chunks/next/dist/client/components/builtin/global-error-68ea4ac05dcaf701.js +1 -0
- package/dist/web-dist/_next/static/chunks/next/dist/client/components/builtin/not-found-bce6d30fb2b1a3b0.js +1 -0
- package/dist/web-dist/_next/static/chunks/next/dist/client/components/builtin/unauthorized-bce6d30fb2b1a3b0.js +1 -0
- package/dist/web-dist/_next/static/chunks/polyfills-42372ed130431b0a.js +1 -0
- package/dist/web-dist/_next/static/chunks/webpack-9073f434bc17ce16.js +1 -0
- package/dist/web-dist/_next/static/css/ceeb8e5596664b11.css +1 -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/apple-icon.png +0 -0
- package/dist/web-dist/apple-touch-icon.png +0 -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/favicon.svg +4 -0
- package/dist/web-dist/icon.svg +4 -0
- package/dist/web-dist/index.html +1 -0
- package/dist/web-dist/index.txt +32 -0
- package/dist/web-dist/live2d/live2dcubismcore.min.js +9 -0
- package/dist/web-dist/logo-circle.png +0 -0
- package/dist/web-dist/logo-circle.svg +4 -0
- package/dist/web-dist/logo-white.svg +3 -0
- package/dist/web-dist/logo.png +0 -0
- package/dist/web-dist/logo.svg +3 -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 +589 -0
- package/package.json +44 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,607 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
4
|
+
if (k2 === undefined) k2 = k;
|
|
5
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
6
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
7
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
8
|
+
}
|
|
9
|
+
Object.defineProperty(o, k2, desc);
|
|
10
|
+
}) : (function(o, m, k, k2) {
|
|
11
|
+
if (k2 === undefined) k2 = k;
|
|
12
|
+
o[k2] = m[k];
|
|
13
|
+
}));
|
|
14
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
15
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
16
|
+
}) : function(o, v) {
|
|
17
|
+
o["default"] = v;
|
|
18
|
+
});
|
|
19
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
20
|
+
var ownKeys = function(o) {
|
|
21
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
22
|
+
var ar = [];
|
|
23
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
24
|
+
return ar;
|
|
25
|
+
};
|
|
26
|
+
return ownKeys(o);
|
|
27
|
+
};
|
|
28
|
+
return function (mod) {
|
|
29
|
+
if (mod && mod.__esModule) return mod;
|
|
30
|
+
var result = {};
|
|
31
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
32
|
+
__setModuleDefault(result, mod);
|
|
33
|
+
return result;
|
|
34
|
+
};
|
|
35
|
+
})();
|
|
36
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
37
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
38
|
+
};
|
|
39
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
40
|
+
exports.colors = exports.CLI_VERSION = void 0;
|
|
41
|
+
exports.printHeader = printHeader;
|
|
42
|
+
exports.printSection = printSection;
|
|
43
|
+
exports.printSuccess = printSuccess;
|
|
44
|
+
exports.projectDirectoryName = projectDirectoryName;
|
|
45
|
+
exports.validateProjectDirectory = validateProjectDirectory;
|
|
46
|
+
exports.formatReviewSummary = formatReviewSummary;
|
|
47
|
+
exports.withTask = withTask;
|
|
48
|
+
exports.runCreateWizard = runCreateWizard;
|
|
49
|
+
exports.runCliDoctor = runCliDoctor;
|
|
50
|
+
exports.runCliReset = runCliReset;
|
|
51
|
+
exports.runCliDb = runCliDb;
|
|
52
|
+
const node_child_process_1 = require("node:child_process");
|
|
53
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
54
|
+
const promises_1 = require("node:fs/promises");
|
|
55
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
56
|
+
const node_util_1 = require("node:util");
|
|
57
|
+
const inquirer_1 = __importDefault(require("inquirer"));
|
|
58
|
+
const discovery_1 = require("./discovery");
|
|
59
|
+
const generator_1 = require("./generator");
|
|
60
|
+
const doctor_1 = require("./doctor");
|
|
61
|
+
const db_1 = require("./db");
|
|
62
|
+
const configurators_1 = require("./configurators");
|
|
63
|
+
const execFile = (0, node_util_1.promisify)(node_child_process_1.execFile);
|
|
64
|
+
exports.CLI_VERSION = '2.1.0';
|
|
65
|
+
const colors_1 = require("./colors");
|
|
66
|
+
Object.defineProperty(exports, "colors", { enumerable: true, get: function () { return colors_1.colors; } });
|
|
67
|
+
function printHeader() {
|
|
68
|
+
console.log(`\n${colors_1.colors.cyan}◈ SIDURI${colors_1.colors.reset} ${colors_1.colors.dim}companion setup (manifest-driven)${colors_1.colors.reset}`);
|
|
69
|
+
console.log(`${colors_1.colors.yellow}Version ${exports.CLI_VERSION}${colors_1.colors.reset} · composable standalone architecture\n`);
|
|
70
|
+
}
|
|
71
|
+
function printSection(title) {
|
|
72
|
+
console.log(`\n${colors_1.colors.cyan}── ${title} ${'─'.repeat(Math.max(2, 42 - title.length))}${colors_1.colors.reset}\n`);
|
|
73
|
+
}
|
|
74
|
+
function printSuccess(message) {
|
|
75
|
+
console.log(`${colors_1.colors.green}✓${colors_1.colors.reset} ${message}`);
|
|
76
|
+
}
|
|
77
|
+
function projectDirectoryName(value) {
|
|
78
|
+
return (value || '').trim() || 'Companion';
|
|
79
|
+
}
|
|
80
|
+
function validateProjectDirectory(value) {
|
|
81
|
+
const trimmed = (value || '').trim();
|
|
82
|
+
if (!trimmed) {
|
|
83
|
+
return 'Please enter a project directory.';
|
|
84
|
+
}
|
|
85
|
+
if (/^\d+$/.test(trimmed) || !isNaN(Number(trimmed))) {
|
|
86
|
+
return 'Project directory cannot be a number.';
|
|
87
|
+
}
|
|
88
|
+
const resolved = node_path_1.default.resolve(process.cwd(), trimmed);
|
|
89
|
+
if (node_fs_1.default.existsSync(resolved)) {
|
|
90
|
+
return `Directory "${trimmed}" already exists in the current directory.`;
|
|
91
|
+
}
|
|
92
|
+
return true;
|
|
93
|
+
}
|
|
94
|
+
function formatReviewSummary(projectDirName, selectedManifests, organSummaries) {
|
|
95
|
+
const lines = [];
|
|
96
|
+
lines.push(`\n${colors_1.colors.cyan}── Review ${projectDirName} ${'─'.repeat(Math.max(2, 42 - (projectDirName.length + 9)))}${colors_1.colors.reset}\n`);
|
|
97
|
+
lines.push(` ${colors_1.colors.bold}Project${colors_1.colors.reset}`);
|
|
98
|
+
lines.push(` ${colors_1.colors.dim}Directory:${colors_1.colors.reset} ${projectDirName}\n`);
|
|
99
|
+
for (const m of selectedManifests) {
|
|
100
|
+
const isRequired = m.organType === 'brain';
|
|
101
|
+
const tag = isRequired ? ` ${colors_1.colors.dim}· required${colors_1.colors.reset}` : '';
|
|
102
|
+
lines.push(` ${colors_1.colors.bold}${m.displayName.split(' ')[0] || m.organType}${colors_1.colors.reset}${tag}`);
|
|
103
|
+
const summary = organSummaries[m.configKey] || organSummaries[m.organType] || {};
|
|
104
|
+
const entries = Object.entries(summary);
|
|
105
|
+
if (entries.length === 0) {
|
|
106
|
+
lines.push(` ${colors_1.colors.dim}Provider:${colors_1.colors.reset} ${m.displayName}`);
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
for (const [key, val] of entries) {
|
|
110
|
+
const valStr = String(val);
|
|
111
|
+
lines.push(` ${colors_1.colors.dim}${key}:${colors_1.colors.reset}${' '.repeat(Math.max(1, 10 - key.length))}${valStr}`);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
lines.push('');
|
|
115
|
+
}
|
|
116
|
+
lines.push(`${colors_1.colors.cyan}${'─'.repeat(46)}${colors_1.colors.reset}\n`);
|
|
117
|
+
return lines.join('\n');
|
|
118
|
+
}
|
|
119
|
+
async function withTask(label, task) {
|
|
120
|
+
process.stdout.write(`${colors_1.colors.dim}${label}${colors_1.colors.reset}`);
|
|
121
|
+
const frames = ['·', '•', '●', '•'];
|
|
122
|
+
let index = 0;
|
|
123
|
+
const timer = setInterval(() => {
|
|
124
|
+
process.stdout.write(`\r${colors_1.colors.dim}${label} ${frames[index++ % frames.length]}${colors_1.colors.reset}`);
|
|
125
|
+
}, 120);
|
|
126
|
+
try {
|
|
127
|
+
const result = await task();
|
|
128
|
+
clearInterval(timer);
|
|
129
|
+
process.stdout.write(`\r${colors_1.colors.green}✓${colors_1.colors.reset} ${label}\n`);
|
|
130
|
+
return result;
|
|
131
|
+
}
|
|
132
|
+
catch (error) {
|
|
133
|
+
clearInterval(timer);
|
|
134
|
+
process.stdout.write(`\r${colors_1.colors.yellow}!${colors_1.colors.reset} ${label}\n`);
|
|
135
|
+
throw error;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
function nonEmpty(value) {
|
|
139
|
+
return value.trim().length > 0 || 'Please enter a value.';
|
|
140
|
+
}
|
|
141
|
+
async function runCreateWizard(targetDir, options) {
|
|
142
|
+
printHeader();
|
|
143
|
+
// 1. Discover manifests from installed or monorepo packages
|
|
144
|
+
const registry = discovery_1.OrganRegistry.discover();
|
|
145
|
+
const availableManifests = registry.getAll();
|
|
146
|
+
if (availableManifests.length === 0) {
|
|
147
|
+
throw new Error('No @sidurijs/* organ packages found. Please ensure organs are installed or in workspace.');
|
|
148
|
+
}
|
|
149
|
+
printSection('Project Details');
|
|
150
|
+
let projectDirName;
|
|
151
|
+
if (targetDir) {
|
|
152
|
+
const check = validateProjectDirectory(targetDir);
|
|
153
|
+
if (check !== true) {
|
|
154
|
+
console.warn(`${colors_1.colors.yellow}!${colors_1.colors.reset} Provided directory "${targetDir}" is invalid: ${check}\n`);
|
|
155
|
+
const dirAnswers = await inquirer_1.default.prompt([
|
|
156
|
+
{
|
|
157
|
+
type: 'input',
|
|
158
|
+
name: 'directory',
|
|
159
|
+
message: 'Project directory:',
|
|
160
|
+
default: 'Companion',
|
|
161
|
+
validate: validateProjectDirectory,
|
|
162
|
+
},
|
|
163
|
+
]);
|
|
164
|
+
projectDirName = dirAnswers.directory.trim();
|
|
165
|
+
}
|
|
166
|
+
else {
|
|
167
|
+
projectDirName = targetDir.trim();
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
else {
|
|
171
|
+
const dirAnswers = await inquirer_1.default.prompt([
|
|
172
|
+
{
|
|
173
|
+
type: 'input',
|
|
174
|
+
name: 'directory',
|
|
175
|
+
message: 'Project directory:',
|
|
176
|
+
default: 'Companion',
|
|
177
|
+
validate: validateProjectDirectory,
|
|
178
|
+
},
|
|
179
|
+
]);
|
|
180
|
+
projectDirName = dirAnswers.directory.trim();
|
|
181
|
+
}
|
|
182
|
+
const projectDir = node_path_1.default.resolve(process.cwd(), projectDirName);
|
|
183
|
+
printSection('Organ Configuration');
|
|
184
|
+
console.log(`${colors_1.colors.dim}Configuring capability organs for ${projectDirName} sequentially from cognition to physical embodiment.${colors_1.colors.reset}\n`);
|
|
185
|
+
// Canonical organ presentation order: Cognition -> Memory/State -> Identity -> Embodiment & Peripheral
|
|
186
|
+
const canonicalOrder = ['brain', 'memory', 'knowledge', 'behavior', 'voice', 'body', 'mouth', 'hands', 'vision', 'ear', 'observation'];
|
|
187
|
+
const orderedManifests = [...availableManifests].sort((a, b) => {
|
|
188
|
+
const idxA = canonicalOrder.indexOf(a.organType);
|
|
189
|
+
const idxB = canonicalOrder.indexOf(b.organType);
|
|
190
|
+
const valA = idxA === -1 ? 99 : idxA;
|
|
191
|
+
const valB = idxB === -1 ? 99 : idxB;
|
|
192
|
+
return valA - valB;
|
|
193
|
+
});
|
|
194
|
+
const selectedManifests = [];
|
|
195
|
+
const organConfigs = {};
|
|
196
|
+
const organSummaries = {};
|
|
197
|
+
for (const m of orderedManifests) {
|
|
198
|
+
const isRequired = m.organType === 'brain';
|
|
199
|
+
const sectionTitle = isRequired ? `${m.displayName.split(' ')[0] || m.organType} · required` : m.displayName.split(' ')[0] || m.organType;
|
|
200
|
+
printSection(sectionTitle);
|
|
201
|
+
const res = await (0, configurators_1.configureOrgan)(m, {
|
|
202
|
+
companionName: projectDirName,
|
|
203
|
+
existingConfig: organConfigs[m.configKey],
|
|
204
|
+
});
|
|
205
|
+
if (res.config?.provider === 'none') {
|
|
206
|
+
continue;
|
|
207
|
+
}
|
|
208
|
+
selectedManifests.push(m);
|
|
209
|
+
organConfigs[m.configKey] = res.config;
|
|
210
|
+
organSummaries[m.configKey] = res.summary || {};
|
|
211
|
+
}
|
|
212
|
+
// 2. Final Review and Edit Loop
|
|
213
|
+
while (true) {
|
|
214
|
+
console.log(formatReviewSummary(projectDirName, selectedManifests, organSummaries));
|
|
215
|
+
const { reviewAction } = await inquirer_1.default.prompt({
|
|
216
|
+
type: 'list',
|
|
217
|
+
name: 'reviewAction',
|
|
218
|
+
message: `Create ${projectDirName} with this configuration?`,
|
|
219
|
+
choices: [
|
|
220
|
+
{ name: 'Yes, create', value: 'create' },
|
|
221
|
+
{ name: 'Go back and edit', value: 'edit' },
|
|
222
|
+
{ name: 'Cancel', value: 'cancel' },
|
|
223
|
+
],
|
|
224
|
+
});
|
|
225
|
+
if (reviewAction === 'cancel') {
|
|
226
|
+
console.log('Instance creation cancelled.');
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
229
|
+
if (reviewAction === 'create') {
|
|
230
|
+
break;
|
|
231
|
+
}
|
|
232
|
+
if (reviewAction === 'edit') {
|
|
233
|
+
const editChoices = orderedManifests.map((m) => {
|
|
234
|
+
const isSelected = selectedManifests.some((sm) => sm.organType === m.organType);
|
|
235
|
+
return {
|
|
236
|
+
name: `${m.displayName} (${isSelected ? 'Enabled' : 'Disabled / Skipped'})`,
|
|
237
|
+
value: m.configKey,
|
|
238
|
+
};
|
|
239
|
+
});
|
|
240
|
+
editChoices.push({ name: 'Edit all organs in sequence', value: '__ALL__' });
|
|
241
|
+
editChoices.push({ name: 'Back to review', value: '__BACK__' });
|
|
242
|
+
const { organToEdit } = await inquirer_1.default.prompt({
|
|
243
|
+
type: 'list',
|
|
244
|
+
name: 'organToEdit',
|
|
245
|
+
message: 'Which organ would you like to edit?',
|
|
246
|
+
choices: editChoices,
|
|
247
|
+
});
|
|
248
|
+
if (organToEdit === '__BACK__') {
|
|
249
|
+
continue;
|
|
250
|
+
}
|
|
251
|
+
const organsToReconfigure = organToEdit === '__ALL__'
|
|
252
|
+
? orderedManifests
|
|
253
|
+
: orderedManifests.filter((m) => m.configKey === organToEdit);
|
|
254
|
+
for (const m of organsToReconfigure) {
|
|
255
|
+
const isRequired = m.organType === 'brain';
|
|
256
|
+
const sectionTitle = isRequired ? `${m.displayName.split(' ')[0] || m.organType} · required` : m.displayName.split(' ')[0] || m.organType;
|
|
257
|
+
printSection(sectionTitle);
|
|
258
|
+
const res = await (0, configurators_1.configureOrgan)(m, {
|
|
259
|
+
companionName: projectDirName,
|
|
260
|
+
existingConfig: organConfigs[m.configKey],
|
|
261
|
+
});
|
|
262
|
+
if (res.config?.provider === 'none') {
|
|
263
|
+
const idx = selectedManifests.findIndex((sm) => sm.organType === m.organType);
|
|
264
|
+
if (idx !== -1)
|
|
265
|
+
selectedManifests.splice(idx, 1);
|
|
266
|
+
delete organConfigs[m.configKey];
|
|
267
|
+
delete organSummaries[m.configKey];
|
|
268
|
+
}
|
|
269
|
+
else {
|
|
270
|
+
if (!selectedManifests.some((sm) => sm.organType === m.organType)) {
|
|
271
|
+
selectedManifests.push(m);
|
|
272
|
+
selectedManifests.sort((a, b) => {
|
|
273
|
+
const idxA = canonicalOrder.indexOf(a.organType);
|
|
274
|
+
const idxB = canonicalOrder.indexOf(b.organType);
|
|
275
|
+
return (idxA === -1 ? 99 : idxA) - (idxB === -1 ? 99 : idxB);
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
organConfigs[m.configKey] = res.config;
|
|
279
|
+
organSummaries[m.configKey] = res.summary || {};
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
// 4. Generate Instance Files
|
|
285
|
+
const files = (0, generator_1.generateInstanceFiles)({
|
|
286
|
+
name: projectDirName,
|
|
287
|
+
selectedManifests,
|
|
288
|
+
organConfigs,
|
|
289
|
+
localPath: options?.localPath,
|
|
290
|
+
});
|
|
291
|
+
await (0, promises_1.mkdir)(projectDir, { recursive: true });
|
|
292
|
+
await (0, promises_1.mkdir)(node_path_1.default.join(projectDir, 'src'), { recursive: true });
|
|
293
|
+
const publicDir = node_path_1.default.join(projectDir, 'public');
|
|
294
|
+
await (0, promises_1.mkdir)(publicDir, { recursive: true });
|
|
295
|
+
await (0, promises_1.writeFile)(node_path_1.default.join(projectDir, 'package.json'), files['package.json'], 'utf8');
|
|
296
|
+
await (0, promises_1.writeFile)(node_path_1.default.join(projectDir, 'siduri.config.json'), files['siduri.config.json'], 'utf8');
|
|
297
|
+
await (0, promises_1.writeFile)(node_path_1.default.join(projectDir, 'siduri.schema.json'), files['siduri.schema.json'], 'utf8');
|
|
298
|
+
await (0, promises_1.writeFile)(node_path_1.default.join(projectDir, '.env.example'), files['.env.example'], 'utf8');
|
|
299
|
+
await (0, promises_1.writeFile)(node_path_1.default.join(projectDir, 'README.md'), files['README.md'], 'utf8');
|
|
300
|
+
await (0, promises_1.writeFile)(node_path_1.default.join(projectDir, 'src/index.js'), files['src/index.js'], 'utf8');
|
|
301
|
+
// Copy full Next.js apps/web production build if present
|
|
302
|
+
const webDistCandidates = [
|
|
303
|
+
node_path_1.default.resolve(__dirname, 'web-dist'),
|
|
304
|
+
node_path_1.default.resolve(__dirname, '../dist/web-dist'),
|
|
305
|
+
node_path_1.default.resolve(__dirname, '../../apps/web/out'),
|
|
306
|
+
node_path_1.default.resolve(process.cwd(), 'apps/web/out'),
|
|
307
|
+
];
|
|
308
|
+
const foundWebDist = webDistCandidates.find((p) => node_fs_1.default.existsSync(p));
|
|
309
|
+
if (foundWebDist) {
|
|
310
|
+
node_fs_1.default.cpSync(foundWebDist, publicDir, { recursive: true });
|
|
311
|
+
}
|
|
312
|
+
else {
|
|
313
|
+
await (0, promises_1.writeFile)(node_path_1.default.join(publicDir, 'index.html'), files['public/index.html'], 'utf8');
|
|
314
|
+
}
|
|
315
|
+
if (files.createAssetsDirs && files.createAssetsDirs.length > 0) {
|
|
316
|
+
for (const dir of files.createAssetsDirs) {
|
|
317
|
+
await (0, promises_1.mkdir)(node_path_1.default.join(projectDir, dir), { recursive: true });
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
else if (files.createAssetsBodyDir) {
|
|
321
|
+
await (0, promises_1.mkdir)(node_path_1.default.join(projectDir, 'assets/body'), { recursive: true });
|
|
322
|
+
}
|
|
323
|
+
// Write all additional generated files (such as assets/self/default.self or other assets)
|
|
324
|
+
const handledKeys = new Set([
|
|
325
|
+
'package.json',
|
|
326
|
+
'siduri.config.json',
|
|
327
|
+
'siduri.schema.json',
|
|
328
|
+
'.env.example',
|
|
329
|
+
'README.md',
|
|
330
|
+
'src/index.js',
|
|
331
|
+
'public/index.html',
|
|
332
|
+
'createAssetsDirs',
|
|
333
|
+
'createAssetsBodyDir',
|
|
334
|
+
]);
|
|
335
|
+
for (const [relPath, content] of Object.entries(files)) {
|
|
336
|
+
if (handledKeys.has(relPath) || typeof content !== 'string')
|
|
337
|
+
continue;
|
|
338
|
+
const destPath = node_path_1.default.join(projectDir, relPath);
|
|
339
|
+
await (0, promises_1.mkdir)(node_path_1.default.dirname(destPath), { recursive: true });
|
|
340
|
+
await (0, promises_1.writeFile)(destPath, content, 'utf8');
|
|
341
|
+
}
|
|
342
|
+
// If local knowledge archive is configured with a download URL, automatically fetch and unpack it
|
|
343
|
+
const knowledgeConfig = organConfigs.knowledge || organConfigs['@sidurijs/knowledge'];
|
|
344
|
+
if (knowledgeConfig?.pack?.mode === 'local' && knowledgeConfig?.pack?.archiveUrl) {
|
|
345
|
+
const packRelDir = (knowledgeConfig.packPath || 'assets/knowledge/pack').replace(/^\.\//, '');
|
|
346
|
+
const packDest = node_path_1.default.join(projectDir, packRelDir);
|
|
347
|
+
try {
|
|
348
|
+
await withTask(`Downloading knowledge archive (${knowledgeConfig.pack.packId || 'pack'})`, async () => {
|
|
349
|
+
const res = await fetch(knowledgeConfig.pack.archiveUrl);
|
|
350
|
+
if (res.ok) {
|
|
351
|
+
const tarPath = node_path_1.default.join(packDest, 'pack.tar.gz');
|
|
352
|
+
const buffer = Buffer.from(await res.arrayBuffer());
|
|
353
|
+
await (0, promises_1.writeFile)(tarPath, buffer);
|
|
354
|
+
await execFile('tar', ['-xzf', tarPath, '-C', packDest]);
|
|
355
|
+
await node_fs_1.default.promises.unlink(tarPath).catch(() => { });
|
|
356
|
+
}
|
|
357
|
+
});
|
|
358
|
+
}
|
|
359
|
+
catch (err) {
|
|
360
|
+
console.warn(`${colors_1.colors.yellow}!${colors_1.colors.reset} Notice: Could not download or unpack knowledge archive: ${err.message}`);
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
printSuccess(`Generated standalone files at ${projectDir}`);
|
|
364
|
+
// 5. Install dependencies from registry
|
|
365
|
+
try {
|
|
366
|
+
await withTask('Installing dependencies (npm install)', async () => {
|
|
367
|
+
await execFile('npm', ['install', '--no-audit', '--no-fund'], { cwd: projectDir });
|
|
368
|
+
});
|
|
369
|
+
printSuccess('Dependencies installed successfully.');
|
|
370
|
+
}
|
|
371
|
+
catch (err) {
|
|
372
|
+
console.warn(`\n${colors_1.colors.yellow}! Notice: npm install failed:${colors_1.colors.reset} ${err.stderr || err.message}`);
|
|
373
|
+
console.warn(`${colors_1.colors.dim}Run "npm install" manually inside ${projectDir} to complete installation.${colors_1.colors.reset}\n`);
|
|
374
|
+
}
|
|
375
|
+
printSection('Instance Ready');
|
|
376
|
+
console.log(`Your Siduri companion is ready! Next steps:\n`);
|
|
377
|
+
console.log(` cd ${node_path_1.default.relative(process.cwd(), projectDir) || '.'}`);
|
|
378
|
+
console.log(` cp .env.example .env ${colors_1.colors.dim}# Fill in required API keys/credentials${colors_1.colors.reset}`);
|
|
379
|
+
console.log(` npm run doctor ${colors_1.colors.dim}# Run diagnostic health probes${colors_1.colors.reset}`);
|
|
380
|
+
console.log(` npm start ${colors_1.colors.dim}# Start Web Companion & Memory Console at http://localhost:3000${colors_1.colors.reset}\n`);
|
|
381
|
+
const voiceConfig = organConfigs.voice || organConfigs['@sidurijs/voice'];
|
|
382
|
+
if (voiceConfig?.provider === 'voicevox') {
|
|
383
|
+
console.log(` ${colors_1.colors.cyan}ℹ Voice Runtime:${colors_1.colors.reset} ${colors_1.colors.dim}VOICEVOX engine (~1.5GB) will auto-download to ~/.voicevox/engine/ and launch on port 50021 on first 'npm start' (if not already running).${colors_1.colors.reset}\n`);
|
|
384
|
+
}
|
|
385
|
+
else if (voiceConfig?.rvc?.enabled) {
|
|
386
|
+
console.log(` ${colors_1.colors.cyan}ℹ Voice Model:${colors_1.colors.reset} ${colors_1.colors.dim}Place your RVC weights (.pth) in ${voiceConfig.rvc.modelPath} before starting voice synthesis.${colors_1.colors.reset}\n`);
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
async function runCliDoctor(targetDir) {
|
|
390
|
+
printHeader();
|
|
391
|
+
const dir = targetDir ? node_path_1.default.resolve(process.cwd(), targetDir) : process.cwd();
|
|
392
|
+
console.log(`${colors_1.colors.cyan}Siduri Doctor${colors_1.colors.reset}`);
|
|
393
|
+
console.log(`${colors_1.colors.dim}─────────────${colors_1.colors.reset}\n`);
|
|
394
|
+
try {
|
|
395
|
+
const report = await (0, doctor_1.runDoctor)({ projectDir: dir });
|
|
396
|
+
console.log(`${colors_1.colors.dim}Instance:${colors_1.colors.reset} ${report.instanceName}`);
|
|
397
|
+
console.log(`${colors_1.colors.dim}Organs:${colors_1.colors.reset} ${report.configuredOrgans.join(', ')}\n`);
|
|
398
|
+
const categories = ['Environment', 'Services', 'Database', 'Health Probe'];
|
|
399
|
+
for (const cat of categories) {
|
|
400
|
+
const items = report.results.filter((r) => r.category === cat);
|
|
401
|
+
if (items.length > 0) {
|
|
402
|
+
console.log(`${colors_1.colors.cyan}${cat}${colors_1.colors.reset}`);
|
|
403
|
+
for (const item of items) {
|
|
404
|
+
if (item.status === 'PASS') {
|
|
405
|
+
console.log(` ${colors_1.colors.green}✓${colors_1.colors.reset} ${item.name} ${colors_1.colors.dim}(${item.message || 'OK'})${colors_1.colors.reset}`);
|
|
406
|
+
}
|
|
407
|
+
else if (item.status === 'OPTIONAL_MISSING') {
|
|
408
|
+
console.log(` ${colors_1.colors.dim}○${colors_1.colors.reset} ${item.name} ${colors_1.colors.dim}(Optional, not set)${colors_1.colors.reset}`);
|
|
409
|
+
}
|
|
410
|
+
else if (item.status === 'SKIPPED') {
|
|
411
|
+
console.log(` ${colors_1.colors.dim}— ${item.name} (${item.message})${colors_1.colors.reset}`);
|
|
412
|
+
}
|
|
413
|
+
else {
|
|
414
|
+
console.log(` ${colors_1.colors.yellow}✗${colors_1.colors.reset} ${item.name}`);
|
|
415
|
+
if (item.organName) {
|
|
416
|
+
console.log(` ${colors_1.colors.dim}Required by:${colors_1.colors.reset} ${item.organName}`);
|
|
417
|
+
}
|
|
418
|
+
if (item.message) {
|
|
419
|
+
console.log(` ${colors_1.colors.yellow}${item.message}${colors_1.colors.reset}`);
|
|
420
|
+
}
|
|
421
|
+
if (item.remediation) {
|
|
422
|
+
console.log(` ${colors_1.colors.dim}Remediation:${colors_1.colors.reset} ${item.remediation}`);
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
console.log();
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
if (report.passed) {
|
|
430
|
+
console.log(`${colors_1.colors.green}Result: PASS${colors_1.colors.reset}\n`);
|
|
431
|
+
process.exitCode = 0;
|
|
432
|
+
}
|
|
433
|
+
else {
|
|
434
|
+
console.log(`${colors_1.colors.yellow}Result: FAIL${colors_1.colors.reset}\n`);
|
|
435
|
+
process.exitCode = 1;
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
catch (err) {
|
|
439
|
+
console.error(`\n${colors_1.colors.yellow}Doctor Error:${colors_1.colors.reset} ${err.message}\n`);
|
|
440
|
+
process.exitCode = 2;
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
async function runCliReset(targetDir) {
|
|
444
|
+
printHeader();
|
|
445
|
+
const dir = targetDir ? node_path_1.default.resolve(process.cwd(), targetDir) : process.cwd();
|
|
446
|
+
console.log(`${colors_1.colors.cyan}Siduri State Reset${colors_1.colors.reset}`);
|
|
447
|
+
console.log(`${colors_1.colors.dim}──────────────────${colors_1.colors.reset}\n`);
|
|
448
|
+
try {
|
|
449
|
+
let dbPath = 'siduri.sqlite';
|
|
450
|
+
let companionId = 'default';
|
|
451
|
+
const configPath = node_path_1.default.join(dir, 'siduri.config.json');
|
|
452
|
+
if (node_fs_1.default.existsSync(configPath)) {
|
|
453
|
+
try {
|
|
454
|
+
const config = JSON.parse(node_fs_1.default.readFileSync(configPath, 'utf8'));
|
|
455
|
+
if (config.id)
|
|
456
|
+
companionId = config.id;
|
|
457
|
+
if (config.organs?.memory?.dbPath)
|
|
458
|
+
dbPath = config.organs.memory.dbPath;
|
|
459
|
+
}
|
|
460
|
+
catch { }
|
|
461
|
+
}
|
|
462
|
+
const fullDbPath = node_path_1.default.resolve(dir, dbPath);
|
|
463
|
+
if (!node_fs_1.default.existsSync(fullDbPath)) {
|
|
464
|
+
console.log(`${colors_1.colors.dim}No database file found at ${fullDbPath}. Already at clean slate.${colors_1.colors.reset}\n`);
|
|
465
|
+
process.exitCode = 0;
|
|
466
|
+
return;
|
|
467
|
+
}
|
|
468
|
+
const tables = [
|
|
469
|
+
'memory_claims',
|
|
470
|
+
'memory_events',
|
|
471
|
+
'self_directives',
|
|
472
|
+
'self_relationships',
|
|
473
|
+
'self_identity',
|
|
474
|
+
'self_personality',
|
|
475
|
+
'self_exemplars',
|
|
476
|
+
'life_entities',
|
|
477
|
+
'life_events',
|
|
478
|
+
'life_finance',
|
|
479
|
+
'life_inventory',
|
|
480
|
+
'life_preferences',
|
|
481
|
+
'life_schedule',
|
|
482
|
+
'life_tasks',
|
|
483
|
+
'system_logs',
|
|
484
|
+
];
|
|
485
|
+
const { DatabaseSync } = await Promise.resolve().then(() => __importStar(require('node:sqlite')));
|
|
486
|
+
const db = new DatabaseSync(fullDbPath);
|
|
487
|
+
try {
|
|
488
|
+
for (const table of tables) {
|
|
489
|
+
try {
|
|
490
|
+
db.prepare(`DELETE FROM ${table} WHERE companion_id = ?`).run(companionId);
|
|
491
|
+
}
|
|
492
|
+
catch {
|
|
493
|
+
try {
|
|
494
|
+
db.prepare(`DELETE FROM ${table}`).run();
|
|
495
|
+
}
|
|
496
|
+
catch { }
|
|
497
|
+
}
|
|
498
|
+
if (companionId !== 'default') {
|
|
499
|
+
try {
|
|
500
|
+
db.prepare(`DELETE FROM ${table} WHERE companion_id = "default"`).run();
|
|
501
|
+
}
|
|
502
|
+
catch { }
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
try {
|
|
506
|
+
db.exec('VACUUM');
|
|
507
|
+
}
|
|
508
|
+
catch { }
|
|
509
|
+
}
|
|
510
|
+
finally {
|
|
511
|
+
db.close();
|
|
512
|
+
}
|
|
513
|
+
printSuccess(`Companion state reset to blank slate:`);
|
|
514
|
+
console.log(` ${colors_1.colors.dim}• Memory claims and events cleared${colors_1.colors.reset}`);
|
|
515
|
+
console.log(` ${colors_1.colors.dim}• Self directives, identity, and relationships cleared${colors_1.colors.reset}`);
|
|
516
|
+
console.log(` ${colors_1.colors.dim}• Life DB (entities, tasks, schedule, events) cleared${colors_1.colors.reset}`);
|
|
517
|
+
console.log(` ${colors_1.colors.dim}• System logs cleared${colors_1.colors.reset}`);
|
|
518
|
+
console.log(`\nInstance is now in a clean blank slate state for testing.\n`);
|
|
519
|
+
process.exitCode = 0;
|
|
520
|
+
}
|
|
521
|
+
catch (err) {
|
|
522
|
+
console.error(`\n${colors_1.colors.yellow}Reset Error:${colors_1.colors.reset} ${err.message}\n`);
|
|
523
|
+
process.exitCode = 1;
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
async function runCliDb(subcommand, targetDir) {
|
|
527
|
+
printHeader();
|
|
528
|
+
if (subcommand === 'reset') {
|
|
529
|
+
await runCliReset(targetDir);
|
|
530
|
+
return;
|
|
531
|
+
}
|
|
532
|
+
if (subcommand !== 'push') {
|
|
533
|
+
console.log('Usage: siduri db push | siduri db reset');
|
|
534
|
+
process.exitCode = 2;
|
|
535
|
+
return;
|
|
536
|
+
}
|
|
537
|
+
const dir = targetDir ? node_path_1.default.resolve(process.cwd(), targetDir) : process.cwd();
|
|
538
|
+
console.log(`${colors_1.colors.cyan}Siduri Database Migrations${colors_1.colors.reset}`);
|
|
539
|
+
console.log(`${colors_1.colors.dim}──────────────────────────${colors_1.colors.reset}\n`);
|
|
540
|
+
try {
|
|
541
|
+
const res = await (0, db_1.runDbPush)({ projectDir: dir });
|
|
542
|
+
if (res.status === 'NOOP') {
|
|
543
|
+
console.log(`${colors_1.colors.dim}— ${res.message}${colors_1.colors.reset}\n`);
|
|
544
|
+
}
|
|
545
|
+
else {
|
|
546
|
+
printSuccess(res.message);
|
|
547
|
+
if (res.appliedMigrations.length > 0) {
|
|
548
|
+
console.log(`${colors_1.colors.dim}Applied:${colors_1.colors.reset} ${res.appliedMigrations.join(', ')}`);
|
|
549
|
+
}
|
|
550
|
+
console.log();
|
|
551
|
+
}
|
|
552
|
+
process.exitCode = 0;
|
|
553
|
+
}
|
|
554
|
+
catch (err) {
|
|
555
|
+
console.error(`\n${colors_1.colors.yellow}Database Migration Error:${colors_1.colors.reset} ${err.message}\n`);
|
|
556
|
+
process.exitCode = 3;
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
async function main() {
|
|
560
|
+
const args = process.argv.slice(2);
|
|
561
|
+
const command = args[0];
|
|
562
|
+
if (command === '--version' || command === '-v') {
|
|
563
|
+
console.log(exports.CLI_VERSION);
|
|
564
|
+
return;
|
|
565
|
+
}
|
|
566
|
+
if (command === 'create') {
|
|
567
|
+
const isLocal = args.includes('--local') || args.includes('--dev') || process.env.SIDURI_LOCAL_DEV === 'true';
|
|
568
|
+
const nonFlags = args.slice(1).filter((a) => !a.startsWith('--'));
|
|
569
|
+
const targetDir = nonFlags[0];
|
|
570
|
+
const localRepo = isLocal ? node_path_1.default.resolve(__dirname, '../..') : undefined;
|
|
571
|
+
await runCreateWizard(targetDir, { localPath: localRepo });
|
|
572
|
+
return;
|
|
573
|
+
}
|
|
574
|
+
if (command === 'reset') {
|
|
575
|
+
const targetDir = args[1];
|
|
576
|
+
await runCliReset(targetDir);
|
|
577
|
+
return;
|
|
578
|
+
}
|
|
579
|
+
if (command === 'doctor') {
|
|
580
|
+
const targetDir = args[1];
|
|
581
|
+
await runCliDoctor(targetDir);
|
|
582
|
+
return;
|
|
583
|
+
}
|
|
584
|
+
if (command === 'db') {
|
|
585
|
+
const subcommand = args[1];
|
|
586
|
+
const targetDir = args[2];
|
|
587
|
+
await runCliDb(subcommand, targetDir);
|
|
588
|
+
return;
|
|
589
|
+
}
|
|
590
|
+
printHeader();
|
|
591
|
+
console.log('Usage: npx siduri create [directory] [--local]');
|
|
592
|
+
console.log(' npx siduri reset [directory]');
|
|
593
|
+
console.log(' npx siduri doctor [directory]');
|
|
594
|
+
console.log(' npx siduri db push [directory]');
|
|
595
|
+
console.log(' npx siduri db reset [directory]');
|
|
596
|
+
console.log(' npx siduri --version\n');
|
|
597
|
+
}
|
|
598
|
+
if (require.main === module) {
|
|
599
|
+
main().catch((error) => {
|
|
600
|
+
if (error && typeof error === 'object' && 'name' in error && error.name === 'ExitPromptError') {
|
|
601
|
+
console.log('\nOperation cancelled.');
|
|
602
|
+
return;
|
|
603
|
+
}
|
|
604
|
+
console.error(`\n${colors_1.colors.yellow}!${colors_1.colors.reset} ${error instanceof Error ? error.message : error}`);
|
|
605
|
+
process.exitCode = 1;
|
|
606
|
+
});
|
|
607
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
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: '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;
|
package/dist/manifest.js
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.validateOrganManifest = validateOrganManifest;
|
|
4
|
+
function validateOrganManifest(manifest, sourcePath) {
|
|
5
|
+
if (!manifest || typeof manifest !== 'object') {
|
|
6
|
+
throw new Error(`Invalid manifest at ${sourcePath || 'unknown'}: expected an object`);
|
|
7
|
+
}
|
|
8
|
+
const m = manifest;
|
|
9
|
+
if (!m.name || typeof m.name !== 'string' || !m.name.startsWith('@sidurijs/')) {
|
|
10
|
+
throw new Error(`Invalid manifest name in ${sourcePath || 'unknown'}: expected package name starting with @sidurijs/`);
|
|
11
|
+
}
|
|
12
|
+
if (!m.organType || typeof m.organType !== 'string') {
|
|
13
|
+
throw new Error(`Invalid manifest organType in ${sourcePath || m.name}`);
|
|
14
|
+
}
|
|
15
|
+
if (!m.version || typeof m.version !== 'string') {
|
|
16
|
+
throw new Error(`Invalid manifest version in ${sourcePath || m.name}`);
|
|
17
|
+
}
|
|
18
|
+
if (!m.displayName || typeof m.displayName !== 'string') {
|
|
19
|
+
throw new Error(`Invalid manifest displayName in ${sourcePath || m.name}`);
|
|
20
|
+
}
|
|
21
|
+
if (!m.entrypoint || typeof m.entrypoint !== 'string') {
|
|
22
|
+
throw new Error(`Invalid manifest entrypoint in ${sourcePath || m.name}`);
|
|
23
|
+
}
|
|
24
|
+
if (!m.factory || typeof m.factory !== 'string') {
|
|
25
|
+
throw new Error(`Invalid manifest factory in ${sourcePath || m.name}`);
|
|
26
|
+
}
|
|
27
|
+
if (!m.configKey || typeof m.configKey !== 'string') {
|
|
28
|
+
throw new Error(`Invalid manifest configKey in ${sourcePath || m.name}`);
|
|
29
|
+
}
|
|
30
|
+
if (!m.configSchema || typeof m.configSchema !== 'object') {
|
|
31
|
+
throw new Error(`Invalid manifest configSchema in ${sourcePath || m.name}`);
|
|
32
|
+
}
|
|
33
|
+
if (!Array.isArray(m.environment)) {
|
|
34
|
+
throw new Error(`Invalid manifest environment in ${sourcePath || m.name}: expected array`);
|
|
35
|
+
}
|
|
36
|
+
if (!Array.isArray(m.services)) {
|
|
37
|
+
throw new Error(`Invalid manifest services in ${sourcePath || m.name}: expected array`);
|
|
38
|
+
}
|
|
39
|
+
return m;
|
|
40
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|