@vxnus/siduri 2.0.5 → 2.0.6

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.
@@ -13,8 +13,16 @@ async function configureEar(_context) {
13
13
  choices: [
14
14
  { name: 'Text Chat (Standard multimodal chat ingress)', value: 'text_chat' },
15
15
  { name: 'Audio Streaming Ingress', value: 'audio_stream' },
16
+ { name: 'None (Skip / Disable sensory ingress)', value: 'none' },
16
17
  ],
18
+ default: 'none',
17
19
  });
20
+ if (defaultSource === 'none') {
21
+ return {
22
+ config: { provider: 'none' },
23
+ summary: { Provider: 'None (Ear disabled)' },
24
+ };
25
+ }
18
26
  return {
19
27
  config: {
20
28
  defaultSource,
@@ -6,6 +6,22 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.configureHands = configureHands;
7
7
  const inquirer_1 = __importDefault(require("inquirer"));
8
8
  async function configureHands(_context) {
9
+ const { provider } = await inquirer_1.default.prompt({
10
+ type: 'list',
11
+ name: 'provider',
12
+ message: 'Hands tool execution engine?',
13
+ choices: [
14
+ { name: 'MCP Client (Model Context Protocol & signed capability tokens)', value: 'mcp' },
15
+ { name: 'None (Skip / No external tool execution)', value: 'none' },
16
+ ],
17
+ default: 'none',
18
+ });
19
+ if (provider === 'none') {
20
+ return {
21
+ config: { provider: 'none' },
22
+ summary: { Provider: 'None (Hands disabled)' },
23
+ };
24
+ }
9
25
  const { timeoutSeconds } = await inquirer_1.default.prompt({
10
26
  type: 'input',
11
27
  name: 'timeoutSeconds',
@@ -1,14 +1,34 @@
1
1
  "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
2
5
  Object.defineProperty(exports, "__esModule", { value: true });
3
6
  exports.configureMouth = configureMouth;
7
+ const inquirer_1 = __importDefault(require("inquirer"));
4
8
  async function configureMouth(_context) {
9
+ const { provider } = await inquirer_1.default.prompt({
10
+ type: 'list',
11
+ name: 'provider',
12
+ message: 'Mouth output delivery channel?',
13
+ choices: [
14
+ { name: 'Web Streaming (Server-Sent Events, Live2D visemes & SSML)', value: 'web' },
15
+ { name: 'None (Silent / Disable speech streaming output)', value: 'none' },
16
+ ],
17
+ default: 'web',
18
+ });
19
+ if (provider === 'none') {
20
+ return {
21
+ config: { provider: 'none' },
22
+ summary: { Provider: 'None (Mouth disabled)' },
23
+ };
24
+ }
5
25
  return {
6
26
  config: {
7
27
  defaultMedium: 'web',
8
28
  maxTextLength: 8000,
9
29
  },
10
30
  summary: {
11
- 'Default Medium': 'Web',
31
+ 'Delivery Medium': 'Web SSE Streaming',
12
32
  'Max Text Length': '8000 chars',
13
33
  },
14
34
  };
@@ -1,7 +1,27 @@
1
1
  "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
2
5
  Object.defineProperty(exports, "__esModule", { value: true });
3
6
  exports.configureObservation = configureObservation;
7
+ const inquirer_1 = __importDefault(require("inquirer"));
4
8
  async function configureObservation(_context) {
9
+ const { provider } = await inquirer_1.default.prompt({
10
+ type: 'list',
11
+ name: 'provider',
12
+ message: 'Screen observation & frame capture?',
13
+ choices: [
14
+ { name: 'Frame Ingest (SHA-256 deduplicated visual grounding for vision)', value: 'fixture' },
15
+ { name: 'None (Skip / Disable screen observation)', value: 'none' },
16
+ ],
17
+ default: 'none',
18
+ });
19
+ if (provider === 'none') {
20
+ return {
21
+ config: { provider: 'none' },
22
+ summary: { Provider: 'None (Observation disabled)' },
23
+ };
24
+ }
5
25
  return {
6
26
  config: {},
7
27
  summary: {
@@ -14,8 +14,16 @@ async function configureVision(_context) {
14
14
  { name: 'GPT-4 Vision / GPT-4o (Multimodal OCR & Object Inspection)', value: 'gpt-4-vision' },
15
15
  { name: 'Claude 3.5 Sonnet Vision', value: 'anthropic/claude-3.5-sonnet' },
16
16
  { name: 'Custom Vision Model', value: 'custom' },
17
+ { name: 'None (Skip / Disable visual perception)', value: 'none' },
17
18
  ],
19
+ default: 'none',
18
20
  });
21
+ if (model === 'none') {
22
+ return {
23
+ config: { provider: 'none' },
24
+ summary: { Provider: 'None (Vision disabled)' },
25
+ };
26
+ }
19
27
  let selectedModel = model;
20
28
  if (model === 'custom') {
21
29
  const { customModel } = await inquirer_1.default.prompt({
@@ -302,9 +302,18 @@ describe('Guided Manifest-Driven Configuration UX Specification Tests', () => {
302
302
  expect(result.summary?.['Model Path']).toBe('./assets/body/sparkle/model.model3.json');
303
303
  });
304
304
  test('Hands configurator configures MCP tool execution timeout', async () => {
305
- inquirer_1.default.prompt.mockResolvedValueOnce({ timeoutSeconds: '15' });
305
+ inquirer_1.default.prompt
306
+ .mockResolvedValueOnce({ provider: 'mcp' })
307
+ .mockResolvedValueOnce({ timeoutSeconds: '15' });
306
308
  const result = await (0, hands_1.configureHands)({ companionName: 'Sparkle', manifest: handsManifest });
307
309
  expect(result.config.defaultTimeoutMs).toBe(15000);
310
+ expect(result.summary?.Provider).toBeUndefined();
311
+ });
312
+ test('Hands configurator disables tool execution when none is selected', async () => {
313
+ inquirer_1.default.prompt.mockResolvedValueOnce({ provider: 'none' });
314
+ const result = await (0, hands_1.configureHands)({ companionName: 'Sparkle', manifest: handsManifest });
315
+ expect(result.config.provider).toBe('none');
316
+ expect(result.summary?.Provider).toBe('None (Hands disabled)');
308
317
  });
309
318
  test('Behavior configurator configures active self personality preset', async () => {
310
319
  inquirer_1.default.prompt.mockResolvedValueOnce({ preset: 'cheerful' });
@@ -318,6 +327,12 @@ describe('Guided Manifest-Driven Configuration UX Specification Tests', () => {
318
327
  expect(result.config.provider).toBe('openrouter');
319
328
  expect(result.config.model).toBe('gpt-4-vision');
320
329
  });
330
+ test('Vision configurator disables vision when none is selected', async () => {
331
+ inquirer_1.default.prompt.mockResolvedValueOnce({ model: 'none' });
332
+ const result = await (0, vision_1.configureVision)({ companionName: 'Sparkle', manifest: visionManifest });
333
+ expect(result.config.provider).toBe('none');
334
+ expect(result.summary?.Provider).toBe('None (Vision disabled)');
335
+ });
321
336
  });
322
337
  describe('Review Summary Formatting & Generator Integration', () => {
323
338
  test('formatReviewSummary displays actual configuration values and metadata', () => {
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { OrganManifest } from './manifest';
3
- export declare const CLI_VERSION = "2.0.4";
3
+ export declare const CLI_VERSION = "2.0.6";
4
4
  export declare const colors: {
5
5
  cyan: string;
6
6
  dim: string;
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.4';
29
+ exports.CLI_VERSION = '2.0.6';
30
30
  exports.colors = {
31
31
  cyan: '\u001b[36m',
32
32
  dim: '\u001b[2m',
@@ -120,50 +120,21 @@ async function runCreateWizard(targetDir) {
120
120
  ]);
121
121
  const companionName = basicAnswers.name;
122
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}In Siduri, a companion is assembled from modular capability organs:${exports.colors.reset}`);
125
- console.log(`${exports.colors.dim}• Brain provides central cognition and LLM reasoning (required).${exports.colors.reset}`);
126
- console.log(`${exports.colors.dim}• Select any capability organs below to attach to ${companionName}.${exports.colors.reset}\n`);
127
- // Canonical organ presentation order
128
- const canonicalOrder = ['memory', 'knowledge', 'behavior', 'voice', 'body', 'mouth', 'hands', 'vision', 'ear', 'observation'];
129
- const nonBrainManifests = availableManifests
130
- .filter((m) => m.organType !== 'brain')
131
- .sort((a, b) => {
123
+ printSection('Organ Configuration');
124
+ console.log(`${exports.colors.dim}Configuring capability organs for ${companionName} sequentially from cognition to physical embodiment.${exports.colors.reset}\n`);
125
+ // Canonical organ presentation order: Cognition -> Memory/State -> Identity -> Embodiment & Peripheral
126
+ const canonicalOrder = ['brain', 'memory', 'knowledge', 'behavior', 'voice', 'body', 'mouth', 'hands', 'vision', 'ear', 'observation'];
127
+ const orderedManifests = [...availableManifests].sort((a, b) => {
132
128
  const idxA = canonicalOrder.indexOf(a.organType);
133
129
  const idxB = canonicalOrder.indexOf(b.organType);
134
130
  const valA = idxA === -1 ? 99 : idxA;
135
131
  const valB = idxB === -1 ? 99 : idxB;
136
132
  return valA - valB;
137
133
  });
138
- const isRecommendedType = (type) => ['memory', 'knowledge', 'behavior', 'voice', 'body', 'mouth'].includes(type);
139
- const organChoices = nonBrainManifests.map((m) => ({
140
- name: `${m.displayName} ${exports.colors.dim}— ${m.description}${exports.colors.reset}`,
141
- value: m.organType,
142
- checked: isRecommendedType(m.organType),
143
- }));
144
- const { selectedOrganTypes } = await inquirer_1.default.prompt({
145
- type: 'checkbox',
146
- name: 'selectedOrganTypes',
147
- message: 'Select capability organs to enable:',
148
- choices: organChoices,
149
- });
150
134
  const selectedManifests = [];
151
135
  const organConfigs = {};
152
136
  const organSummaries = {};
153
- // Brain is required by architecture contract for cognition
154
- const brainManifest = registry.get('brain') || availableManifests.find((m) => m.organType === 'brain');
155
- if (brainManifest) {
156
- selectedManifests.push(brainManifest);
157
- }
158
- for (const organType of selectedOrganTypes) {
159
- const m = registry.get(organType) || availableManifests.find((item) => item.organType === organType);
160
- if (m)
161
- selectedManifests.push(m);
162
- }
163
- // 2. Interactive Organ Configuration Stage
164
- printSection('Organ Configuration');
165
- console.log(`${exports.colors.dim}Configure each enabled organ for ${companionName}.${exports.colors.reset}\n`);
166
- for (const m of selectedManifests) {
137
+ for (const m of orderedManifests) {
167
138
  const isRequired = m.organType === 'brain';
168
139
  const sectionTitle = isRequired ? `${m.displayName.split(' ')[0] || m.organType} · required` : m.displayName.split(' ')[0] || m.organType;
169
140
  printSection(sectionTitle);
@@ -171,10 +142,14 @@ async function runCreateWizard(targetDir) {
171
142
  companionName,
172
143
  existingConfig: organConfigs[m.configKey],
173
144
  });
145
+ if (res.config?.provider === 'none') {
146
+ continue;
147
+ }
148
+ selectedManifests.push(m);
174
149
  organConfigs[m.configKey] = res.config;
175
150
  organSummaries[m.configKey] = res.summary || {};
176
151
  }
177
- // 3. Final Review and Edit Loop
152
+ // 2. Final Review and Edit Loop
178
153
  while (true) {
179
154
  console.log(formatReviewSummary(companionName, selectedManifests, organSummaries));
180
155
  const { reviewAction } = await inquirer_1.default.prompt({
@@ -195,10 +170,13 @@ async function runCreateWizard(targetDir) {
195
170
  break;
196
171
  }
197
172
  if (reviewAction === 'edit') {
198
- const editChoices = selectedManifests.map((m) => ({
199
- name: `Edit ${m.displayName}`,
200
- value: m.configKey,
201
- }));
173
+ const editChoices = orderedManifests.map((m) => {
174
+ const isSelected = selectedManifests.some((sm) => sm.organType === m.organType);
175
+ return {
176
+ name: `${m.displayName} (${isSelected ? 'Enabled' : 'Disabled / Skipped'})`,
177
+ value: m.configKey,
178
+ };
179
+ });
202
180
  editChoices.push({ name: 'Edit all organs in sequence', value: '__ALL__' });
203
181
  editChoices.push({ name: 'Back to review', value: '__BACK__' });
204
182
  const { organToEdit } = await inquirer_1.default.prompt({
@@ -211,8 +189,8 @@ async function runCreateWizard(targetDir) {
211
189
  continue;
212
190
  }
213
191
  const organsToReconfigure = organToEdit === '__ALL__'
214
- ? selectedManifests
215
- : selectedManifests.filter((m) => m.configKey === organToEdit);
192
+ ? orderedManifests
193
+ : orderedManifests.filter((m) => m.configKey === organToEdit);
216
194
  for (const m of organsToReconfigure) {
217
195
  const isRequired = m.organType === 'brain';
218
196
  const sectionTitle = isRequired ? `${m.displayName.split(' ')[0] || m.organType} · required` : m.displayName.split(' ')[0] || m.organType;
@@ -221,8 +199,25 @@ async function runCreateWizard(targetDir) {
221
199
  companionName,
222
200
  existingConfig: organConfigs[m.configKey],
223
201
  });
224
- organConfigs[m.configKey] = res.config;
225
- organSummaries[m.configKey] = res.summary || {};
202
+ if (res.config?.provider === 'none') {
203
+ const idx = selectedManifests.findIndex((sm) => sm.organType === m.organType);
204
+ if (idx !== -1)
205
+ selectedManifests.splice(idx, 1);
206
+ delete organConfigs[m.configKey];
207
+ delete organSummaries[m.configKey];
208
+ }
209
+ else {
210
+ if (!selectedManifests.some((sm) => sm.organType === m.organType)) {
211
+ selectedManifests.push(m);
212
+ selectedManifests.sort((a, b) => {
213
+ const idxA = canonicalOrder.indexOf(a.organType);
214
+ const idxB = canonicalOrder.indexOf(b.organType);
215
+ return (idxA === -1 ? 99 : idxA) - (idxB === -1 ? 99 : idxB);
216
+ });
217
+ }
218
+ organConfigs[m.configKey] = res.config;
219
+ organSummaries[m.configKey] = res.summary || {};
220
+ }
226
221
  }
227
222
  }
228
223
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vxnus/siduri",
3
- "version": "2.0.5",
3
+ "version": "2.0.6",
4
4
  "description": "Experimental CLI for installing and configuring Siduri companions",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {