@vxnus/siduri 2.0.8 → 2.0.10
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/dist/configurators/body.js +2 -14
- package/dist/configurators/ear.js +17 -10
- package/dist/configurators/observation.js +11 -5
- package/dist/configurators.test.js +31 -3
- package/dist/generator.js +6 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
|
@@ -22,24 +22,13 @@ async function configureBody(_context) {
|
|
|
22
22
|
};
|
|
23
23
|
}
|
|
24
24
|
const companionSlug = _context.companionName.toLowerCase().replace(/[^a-z0-9_-]/g, '') || 'default';
|
|
25
|
-
const { modelSource
|
|
25
|
+
const { modelSource } = await inquirer_1.default.prompt([
|
|
26
26
|
{
|
|
27
27
|
type: 'input',
|
|
28
28
|
name: 'modelSource',
|
|
29
29
|
message: 'Live2D Model path / URL (.model3.json):',
|
|
30
30
|
default: `./assets/body/${companionSlug}/model.model3.json`,
|
|
31
31
|
},
|
|
32
|
-
{
|
|
33
|
-
type: 'list',
|
|
34
|
-
name: 'initialExpression',
|
|
35
|
-
message: 'Initial avatar expression:',
|
|
36
|
-
choices: [
|
|
37
|
-
{ name: 'Neutral', value: 'neutral' },
|
|
38
|
-
{ name: 'Happy / Cheerful', value: 'happy' },
|
|
39
|
-
{ name: 'Calm', value: 'calm' },
|
|
40
|
-
],
|
|
41
|
-
default: 'neutral',
|
|
42
|
-
},
|
|
43
32
|
]);
|
|
44
33
|
const modelPath = modelSource.trim() || `./assets/body/${companionSlug}/model.model3.json`;
|
|
45
34
|
const isHttpOrAbsolute = modelPath.startsWith('http://') || modelPath.startsWith('https://') || modelPath.startsWith('/');
|
|
@@ -49,12 +38,11 @@ async function configureBody(_context) {
|
|
|
49
38
|
provider: 'live2d',
|
|
50
39
|
modelPath,
|
|
51
40
|
modelUrl: webModelUrl,
|
|
52
|
-
initialExpression,
|
|
41
|
+
initialExpression: 'neutral',
|
|
53
42
|
},
|
|
54
43
|
summary: {
|
|
55
44
|
Provider: 'Live2D',
|
|
56
45
|
'Model Path': modelPath,
|
|
57
|
-
Expression: initialExpression,
|
|
58
46
|
},
|
|
59
47
|
};
|
|
60
48
|
}
|
|
@@ -6,18 +6,23 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.configureEar = configureEar;
|
|
7
7
|
const inquirer_1 = __importDefault(require("inquirer"));
|
|
8
8
|
async function configureEar(_context) {
|
|
9
|
-
const {
|
|
9
|
+
const { choice } = await inquirer_1.default.prompt({
|
|
10
10
|
type: 'list',
|
|
11
|
-
name: '
|
|
12
|
-
message: 'Perception
|
|
11
|
+
name: 'choice',
|
|
12
|
+
message: 'Ear (Sensory Input & Perception Ingress):',
|
|
13
13
|
choices: [
|
|
14
|
-
{
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
{
|
|
15
|
+
name: 'Enabled (Recommended: Active sensory bounds & audio/text ingress validation)',
|
|
16
|
+
value: 'enabled',
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
name: 'None (Skip / Disable sensory ingress)',
|
|
20
|
+
value: 'none',
|
|
21
|
+
},
|
|
17
22
|
],
|
|
18
|
-
default: '
|
|
23
|
+
default: 'enabled',
|
|
19
24
|
});
|
|
20
|
-
if (
|
|
25
|
+
if (choice === 'none') {
|
|
21
26
|
return {
|
|
22
27
|
config: { provider: 'none' },
|
|
23
28
|
summary: { Provider: 'None (Ear disabled)' },
|
|
@@ -25,12 +30,14 @@ async function configureEar(_context) {
|
|
|
25
30
|
}
|
|
26
31
|
return {
|
|
27
32
|
config: {
|
|
28
|
-
defaultSource,
|
|
33
|
+
defaultSource: 'text_chat',
|
|
29
34
|
maxTextLength: 4000,
|
|
30
35
|
maxAudioBytes: 10485760,
|
|
31
36
|
},
|
|
32
37
|
summary: {
|
|
33
|
-
|
|
38
|
+
Status: 'Enabled (Active sensory guard & audio/text ingress)',
|
|
39
|
+
'Max Text': '4,000 characters',
|
|
40
|
+
'Max Audio': '10 MB',
|
|
34
41
|
},
|
|
35
42
|
};
|
|
36
43
|
}
|
|
@@ -9,23 +9,29 @@ async function configureObservation(_context) {
|
|
|
9
9
|
const { provider } = await inquirer_1.default.prompt({
|
|
10
10
|
type: 'list',
|
|
11
11
|
name: 'provider',
|
|
12
|
-
message: 'Screen observation & frame
|
|
12
|
+
message: 'Screen observation & continuous frame ingest:',
|
|
13
13
|
choices: [
|
|
14
|
-
{
|
|
15
|
-
|
|
14
|
+
{
|
|
15
|
+
name: 'None (Disabled as default - Work in progress)',
|
|
16
|
+
value: 'none',
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
name: 'Experimental Frame Ingest (Prototype - requires active vision)',
|
|
20
|
+
value: 'fixture',
|
|
21
|
+
},
|
|
16
22
|
],
|
|
17
23
|
default: 'none',
|
|
18
24
|
});
|
|
19
25
|
if (provider === 'none') {
|
|
20
26
|
return {
|
|
21
27
|
config: { provider: 'none' },
|
|
22
|
-
summary: { Provider: '
|
|
28
|
+
summary: { Provider: 'Disabled (Work in progress)' },
|
|
23
29
|
};
|
|
24
30
|
}
|
|
25
31
|
return {
|
|
26
32
|
config: {},
|
|
27
33
|
summary: {
|
|
28
|
-
Provider: '
|
|
34
|
+
Provider: 'Experimental Frame Ingest (Work in progress)',
|
|
29
35
|
Deduplication: 'Cryptographic SHA-256 Hashing',
|
|
30
36
|
},
|
|
31
37
|
};
|
|
@@ -17,6 +17,8 @@ const body_1 = require("./configurators/body");
|
|
|
17
17
|
const hands_1 = require("./configurators/hands");
|
|
18
18
|
const behavior_1 = require("./configurators/behavior");
|
|
19
19
|
const vision_1 = require("./configurators/vision");
|
|
20
|
+
const ear_1 = require("./configurators/ear");
|
|
21
|
+
const observation_1 = require("./configurators/observation");
|
|
20
22
|
// Mock inquirer.prompt
|
|
21
23
|
jest.mock('inquirer', () => ({
|
|
22
24
|
prompt: jest.fn(),
|
|
@@ -32,6 +34,8 @@ describe('Guided Manifest-Driven Configuration UX Specification Tests', () => {
|
|
|
32
34
|
const handsManifest = registry.get('hands');
|
|
33
35
|
const behaviorManifest = registry.get('behavior');
|
|
34
36
|
const visionManifest = registry.get('vision');
|
|
37
|
+
const earManifest = registry.get('ear');
|
|
38
|
+
const observationManifest = registry.get('observation');
|
|
35
39
|
beforeEach(() => {
|
|
36
40
|
jest.clearAllMocks();
|
|
37
41
|
});
|
|
@@ -287,18 +291,17 @@ describe('Guided Manifest-Driven Configuration UX Specification Tests', () => {
|
|
|
287
291
|
expect(result.config.rvc.pitchShift).toBe(-6);
|
|
288
292
|
expect(result.summary?.['Base TTS']).toBe('piper');
|
|
289
293
|
});
|
|
290
|
-
test('Body configurator configures Live2D
|
|
294
|
+
test('Body configurator configures Live2D and custom model path', async () => {
|
|
291
295
|
inquirer_1.default.prompt
|
|
292
296
|
.mockResolvedValueOnce({ provider: 'live2d' })
|
|
293
297
|
.mockResolvedValueOnce({
|
|
294
298
|
modelSource: './assets/body/sparkle/model.model3.json',
|
|
295
|
-
initialExpression: 'happy',
|
|
296
299
|
});
|
|
297
300
|
const result = await (0, body_1.configureBody)({ companionName: 'Sparkle', manifest: bodyManifest });
|
|
298
301
|
expect(result.config.provider).toBe('live2d');
|
|
299
302
|
expect(result.config.modelPath).toBe('./assets/body/sparkle/model.model3.json');
|
|
300
303
|
expect(result.config.modelUrl).toBe('/assets/body/sparkle/model.model3.json');
|
|
301
|
-
expect(result.config.initialExpression).toBe('
|
|
304
|
+
expect(result.config.initialExpression).toBe('neutral');
|
|
302
305
|
expect(result.summary?.['Model Path']).toBe('./assets/body/sparkle/model.model3.json');
|
|
303
306
|
});
|
|
304
307
|
test('Hands configurator configures MCP tool execution timeout', async () => {
|
|
@@ -348,6 +351,31 @@ describe('Guided Manifest-Driven Configuration UX Specification Tests', () => {
|
|
|
348
351
|
expect(result.config.provider).toBe('none');
|
|
349
352
|
expect(result.summary?.Provider).toBe('None (Vision disabled)');
|
|
350
353
|
});
|
|
354
|
+
test('Ear configurator enables sensory bounds by default', async () => {
|
|
355
|
+
inquirer_1.default.prompt.mockResolvedValueOnce({ choice: 'enabled' });
|
|
356
|
+
const result = await (0, ear_1.configureEar)({ companionName: 'Sparkle', manifest: earManifest });
|
|
357
|
+
expect(result.config.defaultSource).toBe('text_chat');
|
|
358
|
+
expect(result.config.maxTextLength).toBe(4000);
|
|
359
|
+
expect(result.config.maxAudioBytes).toBe(10485760);
|
|
360
|
+
expect(result.summary?.Status).toContain('Enabled');
|
|
361
|
+
});
|
|
362
|
+
test('Ear configurator disables sensory ingress when none is selected', async () => {
|
|
363
|
+
inquirer_1.default.prompt.mockResolvedValueOnce({ choice: 'none' });
|
|
364
|
+
const result = await (0, ear_1.configureEar)({ companionName: 'Sparkle', manifest: earManifest });
|
|
365
|
+
expect(result.config.provider).toBe('none');
|
|
366
|
+
expect(result.summary?.Provider).toBe('None (Ear disabled)');
|
|
367
|
+
});
|
|
368
|
+
test('Observation configurator disables observation by default as work in progress', async () => {
|
|
369
|
+
inquirer_1.default.prompt.mockResolvedValueOnce({ provider: 'none' });
|
|
370
|
+
const result = await (0, observation_1.configureObservation)({ companionName: 'Sparkle', manifest: observationManifest });
|
|
371
|
+
expect(result.config.provider).toBe('none');
|
|
372
|
+
expect(result.summary?.Provider).toContain('Disabled (Work in progress)');
|
|
373
|
+
});
|
|
374
|
+
test('Observation configurator configures experimental fixture ingest when chosen', async () => {
|
|
375
|
+
inquirer_1.default.prompt.mockResolvedValueOnce({ provider: 'fixture' });
|
|
376
|
+
const result = await (0, observation_1.configureObservation)({ companionName: 'Sparkle', manifest: observationManifest });
|
|
377
|
+
expect(result.summary?.Provider).toContain('Work in progress');
|
|
378
|
+
});
|
|
351
379
|
});
|
|
352
380
|
describe('Review Summary Formatting & Generator Integration', () => {
|
|
353
381
|
test('formatReviewSummary displays actual configuration values and metadata', () => {
|
package/dist/generator.js
CHANGED
|
@@ -81,6 +81,7 @@ function generateInstanceFiles(options) {
|
|
|
81
81
|
const hasVoice = manifests.some((m) => m.organType === 'voice');
|
|
82
82
|
const hasBody = manifests.some((m) => m.organType === 'body');
|
|
83
83
|
const hasMouth = manifests.some((m) => m.organType === 'mouth');
|
|
84
|
+
const hasVision = manifests.some((m) => m.organType === 'vision');
|
|
84
85
|
const voiceConfig = options.organConfigs?.voice || options.organConfigs?.['@siduri-x/voice'];
|
|
85
86
|
const isVoicevox = hasVoice && (!voiceConfig || voiceConfig.provider === 'voicevox');
|
|
86
87
|
// 1. package.json
|
|
@@ -209,6 +210,11 @@ function generateInstanceFiles(options) {
|
|
|
209
210
|
instantiationLines.push(`const knowledge = new ${m.factory}({ ...config.organs.${m.configKey}, dbPath: path.resolve(rootDir, config.organs.${m.configKey}?.dbPath || 'siduri.sqlite') });`);
|
|
210
211
|
organMapEntries.push(` ${m.configKey},`);
|
|
211
212
|
}
|
|
213
|
+
else if (m.name === '@siduri-x/observation') {
|
|
214
|
+
const visionArg = hasVision ? 'vision' : '{ analyze: async () => JSON.stringify({ readings: [] }) }';
|
|
215
|
+
instantiationLines.push(`const observation = new ${m.factory}(${visionArg});`);
|
|
216
|
+
organMapEntries.push(` ${m.configKey},`);
|
|
217
|
+
}
|
|
212
218
|
else {
|
|
213
219
|
const varName = m.configKey;
|
|
214
220
|
instantiationLines.push(`const ${varName} = new ${m.factory}(config.organs.${m.configKey});`);
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -26,7 +26,7 @@ const doctor_1 = require("./doctor");
|
|
|
26
26
|
const db_1 = require("./db");
|
|
27
27
|
const configurators_1 = require("./configurators");
|
|
28
28
|
const execFile = (0, node_util_1.promisify)(node_child_process_1.execFile);
|
|
29
|
-
exports.CLI_VERSION = '2.0.
|
|
29
|
+
exports.CLI_VERSION = '2.0.10';
|
|
30
30
|
const colors_1 = require("./colors");
|
|
31
31
|
Object.defineProperty(exports, "colors", { enumerable: true, get: function () { return colors_1.colors; } });
|
|
32
32
|
function printHeader() {
|