daemora 1.0.8 → 1.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.
@@ -87,104 +87,74 @@ export async function runSetupWizard() {
87
87
  ],
88
88
  }));
89
89
 
90
- if (provider === "openai") {
91
- const key = guard(await p.password({ message: "OpenAI API key (sk-...)", validate: (v) => !v ? "Required" : undefined }));
92
- envConfig.OPENAI_API_KEY = key;
93
- envConfig.DEFAULT_MODEL = guard(await p.select({
94
- message: "OpenAI model",
95
- options: [
96
- { value: "openai:gpt-4.1-mini", label: "gpt-4.1-mini", hint: "1M ctx \u2014 fast & affordable (recommended)" },
97
- { value: "openai:gpt-5.2-pro", label: "gpt-5.2-pro", hint: "GPT-5.2 Pro \u2014 highest capability [NEW]" },
98
- { value: "openai:gpt-5.2", label: "gpt-5.2", hint: "GPT-5.2 flagship (Dec 2025) [NEW]" },
99
- { value: "openai:gpt-5", label: "gpt-5", hint: "GPT-5 flagship (Aug 2025)" },
100
- { value: "openai:gpt-5-mini", label: "gpt-5-mini", hint: "GPT-5 Mini \u2014 fast & cheap" },
101
- { value: "openai:gpt-4.1", label: "gpt-4.1", hint: "1M ctx, best instruction following" },
102
- { value: "openai:gpt-4.1-nano", label: "gpt-4.1-nano", hint: "1M ctx, cheapest" },
103
- { value: "openai:o3-pro", label: "o3-pro", hint: "Best reasoning \u2014 most thorough" },
104
- { value: "openai:o4-mini", label: "o4-mini", hint: "Fast reasoning (Apr 2025)" },
105
- { value: "openai:gpt-4o", label: "gpt-4o", hint: "Vision + text (128K ctx)" },
106
- { value: "openai:gpt-4o-mini", label: "gpt-4o-mini", hint: "GPT-4o Mini \u2014 balanced" },
107
- ],
108
- }));
109
- } else if (provider === "anthropic") {
110
- const key = guard(await p.password({ message: "Anthropic API key (sk-ant-...)", validate: (v) => !v ? "Required" : undefined }));
111
- envConfig.ANTHROPIC_API_KEY = key;
112
- envConfig.DEFAULT_MODEL = guard(await p.select({
113
- message: "Claude model",
114
- options: [
115
- { value: "anthropic:claude-sonnet-4-6", label: "claude-sonnet-4-6", hint: "Best speed/intelligence \u2014 coding & agents [NEW]" },
116
- { value: "anthropic:claude-opus-4-6", label: "claude-opus-4-6", hint: "Most intelligent \u2014 extended thinking [NEW]" },
117
- { value: "anthropic:claude-haiku-4-5", label: "claude-haiku-4-5", hint: "Fastest \u2014 high-volume tasks" },
118
- { value: "anthropic:claude-sonnet-4-5-20250929", label: "claude-sonnet-4-5-20250929", hint: "Sonnet 4.5 \u2014 coding & agentic (200K ctx)" },
119
- { value: "anthropic:claude-3-5-sonnet-latest", label: "claude-3-5-sonnet-latest", hint: "3.5 Sonnet \u2014 widely used previous gen" },
120
- ],
121
- }));
122
- } else if (provider === "google") {
123
- const key = guard(await p.password({ message: "Google AI API key", validate: (v) => !v ? "Required" : undefined }));
124
- envConfig.GOOGLE_AI_API_KEY = key;
125
- envConfig.DEFAULT_MODEL = guard(await p.select({
126
- message: "Gemini model",
127
- options: [
128
- { value: "google:gemini-2.5-flash", label: "gemini-2.5-flash", hint: "Fast & cost-effective \u2014 recommended" },
129
- { value: "google:gemini-3.1-pro-preview", label: "gemini-3.1-pro-preview", hint: "Latest \u2014 complex tasks [NEW]" },
130
- { value: "google:gemini-3.1-flash-lite-preview", label: "gemini-3.1-flash-lite-preview", hint: "Latest lite \u2014 cost-efficient [NEW]" },
131
- { value: "google:gemini-2.5-pro", label: "gemini-2.5-pro", hint: "Complex reasoning & coding (1M ctx)" },
132
- { value: "google:gemini-2.5-flash-lite", label: "gemini-2.5-flash-lite", hint: "Speed-optimised high-throughput" },
133
- { value: "google:gemini-2.0-flash", label: "gemini-2.0-flash", hint: "Previous gen flash" },
134
- ],
135
- }));
136
- } else if (provider === "xai") {
137
- const key = guard(await p.password({ message: "xAI API key", validate: (v) => !v ? "Required" : undefined }));
138
- envConfig.XAI_API_KEY = key;
139
- envConfig.DEFAULT_MODEL = guard(await p.select({
140
- message: "Grok model",
141
- options: [
142
- { value: "xai:grok-4", label: "grok-4", hint: "Latest & most capable (Jul 2025) [NEW]" },
143
- { value: "xai:grok-3-beta", label: "grok-3-beta", hint: "Grok 3 Beta \u2014 131K ctx" },
144
- { value: "xai:grok-3-mini-beta", label: "grok-3-mini-beta", hint: "Grok 3 Mini \u2014 fast, 131K ctx" },
145
- ],
146
- }));
147
- } else if (provider === "deepseek") {
148
- const key = guard(await p.password({ message: "DeepSeek API key (sk-...)", validate: (v) => !v ? "Required" : undefined }));
149
- envConfig.DEEPSEEK_API_KEY = key;
150
- envConfig.DEFAULT_MODEL = guard(await p.select({
151
- message: "DeepSeek model",
152
- options: [
153
- { value: "deepseek:deepseek-chat", label: "deepseek-chat", hint: "V3 \u2014 excellent coder (128K ctx, recommended)" },
154
- { value: "deepseek:deepseek-reasoner", label: "deepseek-reasoner", hint: "R1 \u2014 chain-of-thought reasoning" },
155
- ],
156
- }));
157
- } else if (provider === "mistral") {
158
- const key = guard(await p.password({ message: "Mistral API key", validate: (v) => !v ? "Required" : undefined }));
159
- envConfig.MISTRAL_API_KEY = key;
160
- envConfig.DEFAULT_MODEL = guard(await p.select({
161
- message: "Mistral model",
162
- options: [
163
- { value: "mistral:mistral-large-2512", label: "mistral-large-2512", hint: "Flagship \u2014 best quality (Dec 2025) [NEW]" },
164
- { value: "mistral:mistral-medium-3", label: "mistral-medium-3", hint: "Balanced capability & speed" },
165
- { value: "mistral:codestral-2508", label: "codestral-2508", hint: "Code specialist (Aug 2025)" },
166
- { value: "mistral:mistral-small-3.2-24b", label: "mistral-small-3.2-24b", hint: "Lightweight, runs locally (24B)" },
167
- ],
168
- }));
169
- } else if (provider === "ollama") {
90
+ // Load model registry dynamically
91
+ const { models: modelRegistry } = await import("../config/models.js");
92
+
93
+ // Provider config: API key prompt + env var name
94
+ const providerKeys = {
95
+ openai: { env: "OPENAI_API_KEY", prompt: "OpenAI API key (sk-...)" },
96
+ anthropic: { env: "ANTHROPIC_API_KEY", prompt: "Anthropic API key (sk-ant-...)" },
97
+ google: { env: "GOOGLE_AI_API_KEY", prompt: "Google AI API key" },
98
+ xai: { env: "XAI_API_KEY", prompt: "xAI API key" },
99
+ deepseek: { env: "DEEPSEEK_API_KEY", prompt: "DeepSeek API key (sk-...)" },
100
+ mistral: { env: "MISTRAL_API_KEY", prompt: "Mistral API key" },
101
+ };
102
+
103
+ if (provider === "ollama") {
104
+ // Ollama: list known local models from registry + free text input
105
+ const ollamaModels = Object.entries(modelRegistry)
106
+ .filter(([, m]) => m.provider === "ollama")
107
+ .map(([, m]) => m.model);
108
+ const ollamaHint = ollamaModels.length ? ollamaModels.join(", ") : "llama3.1, qwen2.5-coder";
170
109
  p.note(
171
110
  [
172
111
  "Make sure Ollama is running: ollama serve",
173
- "Pull a model first: ollama pull llama4-maverick",
174
- "Recommended models:",
175
- " llama4-maverick \u2014 Llama 4, 17B MoE, multimodal, 1M ctx",
176
- " llama4-scout \u2014 Llama 4, 17B MoE, 10M ctx",
177
- " llama3.3 \u2014 best 70B open model",
178
- " qwen2.5 \u2014 strong coder",
112
+ "Pull a model first: ollama pull <model>",
113
+ `Known models: ${ollamaHint}`,
114
+ "You can use any model available in your Ollama installation.",
179
115
  ].join("\n"),
180
116
  "Ollama (local models)",
181
117
  );
182
118
  const model = guard(await p.text({
183
119
  message: "Ollama model name",
184
- initialValue: "llama4-maverick",
185
- placeholder: "e.g. llama4-maverick, llama3.3, qwen2.5",
120
+ initialValue: ollamaModels[0] || "llama3.1",
121
+ placeholder: `e.g. ${ollamaHint}`,
186
122
  }));
187
123
  envConfig.DEFAULT_MODEL = `ollama:${model}`;
124
+ } else {
125
+ // Cloud provider: ask for API key, then show models from registry
126
+ const keyInfo = providerKeys[provider];
127
+ if (keyInfo) {
128
+ const key = guard(await p.password({ message: keyInfo.prompt, validate: (v) => !v ? "Required" : undefined }));
129
+ envConfig[keyInfo.env] = key;
130
+ }
131
+
132
+ // Build model options from registry for this provider
133
+ const providerModels = Object.entries(modelRegistry)
134
+ .filter(([, m]) => m.provider === provider)
135
+ .map(([id, m]) => {
136
+ const ctx = m.contextWindow >= 1_000_000
137
+ ? `${(m.contextWindow / 1_000_000).toFixed(0)}M ctx`
138
+ : `${(m.contextWindow / 1_000).toFixed(0)}K ctx`;
139
+ const caps = (m.capabilities || []).filter(c => c !== "text" && c !== "tools").join(", ");
140
+ const price = m.costPer1kInput > 0 ? `$${m.costPer1kInput}/1k in` : "free";
141
+ const parts = [ctx, m.tier, caps, price].filter(Boolean);
142
+ return { value: id, label: m.model, hint: parts.join(" \u00b7 ") };
143
+ });
144
+
145
+ if (providerModels.length > 0) {
146
+ envConfig.DEFAULT_MODEL = guard(await p.select({
147
+ message: `${provider.charAt(0).toUpperCase() + provider.slice(1)} model`,
148
+ options: providerModels,
149
+ }));
150
+ } else {
151
+ // Provider not in registry — free text input
152
+ const model = guard(await p.text({
153
+ message: `${provider} model name (e.g. ${provider}:model-name)`,
154
+ validate: (v) => !v ? "Required" : undefined,
155
+ }));
156
+ envConfig.DEFAULT_MODEL = model.includes(":") ? model : `${provider}:${model}`;
157
+ }
188
158
  }
189
159
 
190
160
  p.log.success(`Provider: ${t.bold(provider)} Model: ${t.bold(envConfig.DEFAULT_MODEL)}`);