@vxnus/siduri 0.0.6 → 0.0.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 (39) hide show
  1. package/dist/builtin-manifests.d.ts +2 -0
  2. package/dist/builtin-manifests.js +433 -0
  3. package/dist/clean-machine-e2e.test.js +1 -1
  4. package/dist/configurators/behavior.d.ts +2 -0
  5. package/dist/configurators/behavior.js +36 -0
  6. package/dist/configurators/body.d.ts +2 -0
  7. package/dist/configurators/body.js +44 -0
  8. package/dist/configurators/brain.d.ts +6 -0
  9. package/dist/configurators/brain.js +80 -0
  10. package/dist/configurators/ear.d.ts +2 -0
  11. package/dist/configurators/ear.js +28 -0
  12. package/dist/configurators/hands.d.ts +2 -0
  13. package/dist/configurators/hands.js +27 -0
  14. package/dist/configurators/index.d.ts +23 -0
  15. package/dist/configurators/index.js +74 -0
  16. package/dist/configurators/knowledge.d.ts +6 -0
  17. package/dist/configurators/knowledge.js +100 -0
  18. package/dist/configurators/memory.d.ts +2 -0
  19. package/dist/configurators/memory.js +44 -0
  20. package/dist/configurators/observation.d.ts +2 -0
  21. package/dist/configurators/observation.js +12 -0
  22. package/dist/configurators/types.d.ts +12 -0
  23. package/dist/configurators/types.js +2 -0
  24. package/dist/configurators/vision.d.ts +2 -0
  25. package/dist/configurators/vision.js +39 -0
  26. package/dist/configurators/voice.d.ts +2 -0
  27. package/dist/configurators/voice.js +53 -0
  28. package/dist/configurators.test.d.ts +1 -0
  29. package/dist/configurators.test.js +275 -0
  30. package/dist/discovery.js +8 -0
  31. package/dist/discovery.test.js +7 -0
  32. package/dist/index.d.ts +16 -0
  33. package/dist/index.js +137 -54
  34. package/dist/providers/knowledge-hub.d.ts +37 -0
  35. package/dist/providers/knowledge-hub.js +141 -0
  36. package/dist/providers/openrouter.d.ts +32 -0
  37. package/dist/providers/openrouter.js +201 -0
  38. package/dist/release-check.js +1 -1
  39. package/package.json +1 -1
@@ -0,0 +1,201 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.OpenRouterModelProvider = exports.CURATED_OPENROUTER_MODELS = void 0;
7
+ exports.promptOpenRouterModelSelection = promptOpenRouterModelSelection;
8
+ const inquirer_1 = __importDefault(require("inquirer"));
9
+ exports.CURATED_OPENROUTER_MODELS = [
10
+ { id: 'openai/gpt-4o-mini', name: 'OpenAI: GPT-4o Mini', description: 'Fast, lightweight intelligence' },
11
+ { id: 'openai/gpt-4o', name: 'OpenAI: GPT-4o', description: 'Flagship multimodal intelligence' },
12
+ { id: 'anthropic/claude-3.5-sonnet', name: 'Anthropic: Claude 3.5 Sonnet', description: 'State-of-the-art reasoning and coding' },
13
+ { id: 'anthropic/claude-3-haiku', name: 'Anthropic: Claude 3 Haiku', description: 'Fast and compact' },
14
+ { id: 'google/gemini-2.0-flash-001', name: 'Google: Gemini 2.0 Flash', description: 'Next-gen speed and multimodal capabilities' },
15
+ { id: 'meta-llama/llama-3.3-70b-instruct', name: 'Meta: Llama 3.3 70B Instruct', description: 'High capability open weights model' },
16
+ { id: 'deepseek/deepseek-chat', name: 'DeepSeek: DeepSeek V3', description: 'Advanced conversational and coding model' },
17
+ { id: 'deepseek/deepseek-r1', name: 'DeepSeek: DeepSeek R1', description: 'Advanced reasoning model' },
18
+ { id: 'mistralai/mistral-large', name: 'Mistral: Mistral Large', description: 'Top-tier reasoning and multilingual model' },
19
+ ];
20
+ class OpenRouterModelProvider {
21
+ apiUrl;
22
+ timeoutMs;
23
+ constructor(apiUrl = 'https://openrouter.ai/api/v1/models', timeoutMs = 6000) {
24
+ this.apiUrl = apiUrl;
25
+ this.timeoutMs = timeoutMs;
26
+ }
27
+ async listModels() {
28
+ const controller = new AbortController();
29
+ const timer = setTimeout(() => controller.abort(), this.timeoutMs);
30
+ try {
31
+ const response = await fetch(this.apiUrl, {
32
+ method: 'GET',
33
+ headers: {
34
+ Accept: 'application/json',
35
+ 'User-Agent': 'Siduri-CLI/1.0',
36
+ },
37
+ signal: controller.signal,
38
+ });
39
+ if (!response.ok) {
40
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
41
+ }
42
+ const body = (await response.json());
43
+ if (!body.data || !Array.isArray(body.data) || body.data.length === 0) {
44
+ throw new Error('Received empty or invalid model list from OpenRouter API.');
45
+ }
46
+ return body.data.map((m) => ({
47
+ id: m.id,
48
+ name: m.name || m.id,
49
+ description: m.description,
50
+ contextLength: m.context_length,
51
+ }));
52
+ }
53
+ finally {
54
+ clearTimeout(timer);
55
+ }
56
+ }
57
+ }
58
+ exports.OpenRouterModelProvider = OpenRouterModelProvider;
59
+ /**
60
+ * Interactive model selector with search, pagination, and robust error recovery.
61
+ */
62
+ async function promptOpenRouterModelSelection(provider = new OpenRouterModelProvider()) {
63
+ let models = [];
64
+ let fetchFailed = false;
65
+ let fetchError = '';
66
+ // 1. Fetch models dynamically
67
+ try {
68
+ process.stdout.write('\u001b[2mFetching OpenRouter models...\u001b[0m');
69
+ models = await provider.listModels();
70
+ process.stdout.write('\r\u001b[32m✓\u001b[0m Fetched OpenRouter models catalog\n');
71
+ }
72
+ catch (err) {
73
+ fetchFailed = true;
74
+ fetchError = err.message || String(err);
75
+ process.stdout.write('\r\u001b[33m!\u001b[0m Unable to fetch OpenRouter models.\n');
76
+ }
77
+ // 2. Handle failure if API is unreachable
78
+ if (fetchFailed || models.length === 0) {
79
+ console.log(`\u001b[33mReason:\u001b[0m ${fetchError || 'No models returned.'}\n`);
80
+ const { failureAction } = await inquirer_1.default.prompt({
81
+ type: 'list',
82
+ name: 'failureAction',
83
+ message: 'What would you like to do?',
84
+ choices: [
85
+ { name: 'Retry fetching models', value: 'retry' },
86
+ { name: 'Use curated standard models', value: 'curated' },
87
+ { name: 'Enter model ID manually', value: 'manual' },
88
+ { name: 'Choose another Brain provider', value: 'switch_provider' },
89
+ { name: 'Cancel', value: 'cancel' },
90
+ ],
91
+ });
92
+ if (failureAction === 'retry') {
93
+ return promptOpenRouterModelSelection(provider);
94
+ }
95
+ if (failureAction === 'curated') {
96
+ models = exports.CURATED_OPENROUTER_MODELS;
97
+ }
98
+ else if (failureAction === 'manual') {
99
+ const { manualId } = await inquirer_1.default.prompt({
100
+ type: 'input',
101
+ name: 'manualId',
102
+ message: 'Model ID (e.g. openai/gpt-4o-mini):',
103
+ default: 'openai/gpt-4o-mini',
104
+ validate: (val) => val.trim().length > 0 || 'Please enter a model ID.',
105
+ });
106
+ return { type: 'manual', modelId: manualId.trim() };
107
+ }
108
+ else if (failureAction === 'switch_provider') {
109
+ return { type: 'switch_provider' };
110
+ }
111
+ else {
112
+ return { type: 'cancel' };
113
+ }
114
+ }
115
+ // 3. Selection flow with filtering
116
+ let currentSearch = '';
117
+ while (true) {
118
+ let filtered = models;
119
+ if (currentSearch.trim()) {
120
+ const q = currentSearch.toLowerCase();
121
+ filtered = models.filter((m) => m.name.toLowerCase().includes(q) || m.id.toLowerCase().includes(q));
122
+ }
123
+ const choices = [];
124
+ // Search action at top
125
+ if (currentSearch) {
126
+ choices.push({
127
+ name: `\u001b[36m⌕ Clear filter (currently: "${currentSearch}") [${filtered.length} matches]\u001b[0m`,
128
+ value: '__CLEAR_FILTER__',
129
+ });
130
+ }
131
+ else {
132
+ choices.push({
133
+ name: `\u001b[36m⌕ Search / Filter models by keyword...\u001b[0m`,
134
+ value: '__FILTER__',
135
+ });
136
+ }
137
+ choices.push(new inquirer_1.default.Separator('── Models ──'));
138
+ if (filtered.length === 0) {
139
+ choices.push({
140
+ name: `\u001b[33mNo models matched "${currentSearch}". Search again or enter manually.\u001b[0m`,
141
+ value: '__FILTER__',
142
+ });
143
+ }
144
+ else {
145
+ // Limit to max 40 items displayed per page to prevent UI overload
146
+ const displayList = filtered.slice(0, 40);
147
+ for (const m of displayList) {
148
+ const idLabel = m.name !== m.id ? ` \u001b[2m(${m.id})\u001b[0m` : '';
149
+ choices.push({
150
+ name: `${m.name}${idLabel}`,
151
+ value: m.id,
152
+ });
153
+ }
154
+ if (filtered.length > 40) {
155
+ choices.push(new inquirer_1.default.Separator(`... and ${filtered.length - 40} more (use search to refine)`));
156
+ }
157
+ }
158
+ choices.push(new inquirer_1.default.Separator('── Other Options ──'));
159
+ choices.push({ name: 'Enter model ID manually', value: '__MANUAL__' });
160
+ choices.push({ name: 'Choose another Brain provider', value: '__SWITCH__' });
161
+ const { selectedValue } = await inquirer_1.default.prompt({
162
+ type: 'list',
163
+ name: 'selectedValue',
164
+ message: currentSearch ? `Select model (filtered by "${currentSearch}"):` : 'Select model:',
165
+ pageSize: 15,
166
+ choices,
167
+ });
168
+ if (selectedValue === '__FILTER__') {
169
+ const { query } = await inquirer_1.default.prompt({
170
+ type: 'input',
171
+ name: 'query',
172
+ message: 'Search models (e.g. claude, gpt, gemini, llama):',
173
+ });
174
+ currentSearch = query.trim();
175
+ continue;
176
+ }
177
+ if (selectedValue === '__CLEAR_FILTER__') {
178
+ currentSearch = '';
179
+ continue;
180
+ }
181
+ if (selectedValue === '__MANUAL__') {
182
+ const { manualId } = await inquirer_1.default.prompt({
183
+ type: 'input',
184
+ name: 'manualId',
185
+ message: 'Model ID (e.g. openai/gpt-4o-mini):',
186
+ default: 'openai/gpt-4o-mini',
187
+ validate: (val) => val.trim().length > 0 || 'Please enter a model ID.',
188
+ });
189
+ return { type: 'manual', modelId: manualId.trim() };
190
+ }
191
+ if (selectedValue === '__SWITCH__') {
192
+ return { type: 'switch_provider' };
193
+ }
194
+ const matchedModel = models.find((m) => m.id === selectedValue);
195
+ return {
196
+ type: 'selected',
197
+ modelId: selectedValue,
198
+ modelName: matchedModel?.name || selectedValue,
199
+ };
200
+ }
201
+ }
@@ -28,7 +28,7 @@ function runReleaseCheck(repoRoot = node_path_1.default.resolve(__dirname, '../.
28
28
  { name: '@siduri-x/body', dir: 'packages/organs/body', isOrgan: true, tarName: 'siduri-x-body-1.0.0.tgz' },
29
29
  { name: '@siduri-x/voice', dir: 'packages/organs/voice', isOrgan: true, tarName: 'siduri-x-voice-1.0.0.tgz' },
30
30
  { name: '@siduri-x/observation', dir: 'packages/organs/observation', isOrgan: true, tarName: 'siduri-x-observation-1.0.0.tgz' },
31
- { name: '@vxnus/siduri', dir: 'cli', isOrgan: false, tarName: 'vxnus-siduri-0.0.6.tgz' },
31
+ { name: '@vxnus/siduri', dir: 'cli', isOrgan: false, tarName: 'vxnus-siduri-0.0.8.tgz' },
32
32
  ];
33
33
  let packagesChecked = 0;
34
34
  let tarballsInspected = 0;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vxnus/siduri",
3
- "version": "0.0.6",
3
+ "version": "0.0.8",
4
4
  "description": "Experimental CLI for installing and configuring Siduri companions",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {