@phi-code-admin/phi-code 0.57.5 → 0.57.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.
- package/extensions/phi/init.ts +114 -15
- package/package.json +1 -1
package/extensions/phi/init.ts
CHANGED
|
@@ -23,6 +23,7 @@ interface DetectedProvider {
|
|
|
23
23
|
baseUrl: string;
|
|
24
24
|
models: string[];
|
|
25
25
|
available: boolean;
|
|
26
|
+
local?: boolean; // True for Ollama/LM Studio (models discovered at runtime)
|
|
26
27
|
}
|
|
27
28
|
|
|
28
29
|
interface RoutingConfig {
|
|
@@ -82,15 +83,65 @@ function detectProviders(): DetectedProvider[] {
|
|
|
82
83
|
models: ["llama-3.3-70b-versatile", "mixtral-8x7b-32768"],
|
|
83
84
|
available: false,
|
|
84
85
|
},
|
|
86
|
+
{
|
|
87
|
+
name: "Ollama",
|
|
88
|
+
envVar: "OLLAMA",
|
|
89
|
+
baseUrl: "http://localhost:11434/v1",
|
|
90
|
+
models: [], // Discovered at runtime
|
|
91
|
+
available: false,
|
|
92
|
+
local: true,
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
name: "LM Studio",
|
|
96
|
+
envVar: "LM_STUDIO",
|
|
97
|
+
baseUrl: "http://localhost:1234/v1",
|
|
98
|
+
models: [], // Discovered at runtime
|
|
99
|
+
available: false,
|
|
100
|
+
local: true,
|
|
101
|
+
},
|
|
85
102
|
];
|
|
86
103
|
|
|
87
104
|
for (const p of providers) {
|
|
88
|
-
p.
|
|
105
|
+
if (p.local) {
|
|
106
|
+
// Local providers: check if server is running by probing the URL
|
|
107
|
+
p.available = false; // Will be checked async in detectLocalProviders()
|
|
108
|
+
} else {
|
|
109
|
+
p.available = !!process.env[p.envVar];
|
|
110
|
+
}
|
|
89
111
|
}
|
|
90
112
|
|
|
91
113
|
return providers;
|
|
92
114
|
}
|
|
93
115
|
|
|
116
|
+
/**
|
|
117
|
+
* Detect local providers (Ollama, LM Studio) by probing their endpoints
|
|
118
|
+
* and fetching available models dynamically.
|
|
119
|
+
*/
|
|
120
|
+
async function detectLocalProviders(providers: DetectedProvider[]): Promise<void> {
|
|
121
|
+
for (const p of providers) {
|
|
122
|
+
if (!p.local) continue;
|
|
123
|
+
try {
|
|
124
|
+
const controller = new AbortController();
|
|
125
|
+
const timeout = setTimeout(() => controller.abort(), 3000);
|
|
126
|
+
const res = await fetch(`${p.baseUrl}/models`, {
|
|
127
|
+
signal: controller.signal,
|
|
128
|
+
headers: { Authorization: `Bearer ${p.envVar === "OLLAMA" ? "ollama" : "lm-studio"}` },
|
|
129
|
+
});
|
|
130
|
+
clearTimeout(timeout);
|
|
131
|
+
if (res.ok) {
|
|
132
|
+
const data = await res.json() as any;
|
|
133
|
+
const models = (data.data || []).map((m: any) => m.id).filter(Boolean);
|
|
134
|
+
if (models.length > 0) {
|
|
135
|
+
p.models = models;
|
|
136
|
+
p.available = true;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
} catch {
|
|
140
|
+
// Server not running — that's fine
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
94
145
|
function getAllAvailableModels(providers: DetectedProvider[]): string[] {
|
|
95
146
|
return providers.filter(p => p.available).flatMap(p => p.models);
|
|
96
147
|
}
|
|
@@ -210,18 +261,55 @@ _Edit this file to customize Phi Code's behavior for your project._
|
|
|
210
261
|
|
|
211
262
|
// ─── MODE: Auto ──────────────────────────────────────────────────
|
|
212
263
|
|
|
264
|
+
/**
|
|
265
|
+
* Auto-assign models based on specialization heuristics.
|
|
266
|
+
* Works with ANY provider — not just Alibaba.
|
|
267
|
+
*
|
|
268
|
+
* Strategy: match model names against known specialization patterns.
|
|
269
|
+
* - "coder" in name → code tasks
|
|
270
|
+
* - "mini"/"flash"/"fast"/"small" in name → explore/test (fast tasks)
|
|
271
|
+
* - Largest/best model → plan/debug/review (reasoning tasks)
|
|
272
|
+
* - If only 1 model available → everything uses that model (still works!)
|
|
273
|
+
*/
|
|
213
274
|
function autoMode(availableModels: string[]): Record<string, { preferred: string; fallback: string }> {
|
|
214
275
|
const assignments: Record<string, { preferred: string; fallback: string }> = {};
|
|
215
276
|
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
const
|
|
219
|
-
assignments[role.key] =
|
|
277
|
+
if (availableModels.length === 0) {
|
|
278
|
+
// Shouldn't happen, but safety fallback
|
|
279
|
+
const fb = { preferred: "qwen3.5-plus", fallback: "qwen3.5-plus" };
|
|
280
|
+
for (const role of TASK_ROLES) assignments[role.key] = fb;
|
|
281
|
+
assignments["default"] = fb;
|
|
282
|
+
return assignments;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
if (availableModels.length === 1) {
|
|
286
|
+
// Single model: everything uses it
|
|
287
|
+
const single = { preferred: availableModels[0], fallback: availableModels[0] };
|
|
288
|
+
for (const role of TASK_ROLES) assignments[role.key] = single;
|
|
289
|
+
assignments["default"] = single;
|
|
290
|
+
return assignments;
|
|
220
291
|
}
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
292
|
+
|
|
293
|
+
// Categorize models by name heuristics
|
|
294
|
+
const lower = availableModels.map(m => ({ id: m, l: m.toLowerCase() }));
|
|
295
|
+
const coderModels = lower.filter(m => /coder|code|codestral/.test(m.l)).map(m => m.id);
|
|
296
|
+
const fastModels = lower.filter(m => /mini|flash|fast|small|haiku|lite/.test(m.l)).map(m => m.id);
|
|
297
|
+
const reasoningModels = lower.filter(m => /max|pro|plus|opus|large|o1|o3/.test(m.l)).map(m => m.id);
|
|
298
|
+
|
|
299
|
+
// Pick best for each category, with fallback to first available
|
|
300
|
+
const bestCoder = coderModels[0] || reasoningModels[0] || availableModels[0];
|
|
301
|
+
const bestReasoning = reasoningModels[0] || availableModels[0];
|
|
302
|
+
const bestFast = fastModels[0] || availableModels[availableModels.length - 1] || availableModels[0];
|
|
303
|
+
const generalModel = reasoningModels[0] || availableModels[0];
|
|
304
|
+
const fallbackModel = availableModels.find(m => m !== generalModel) || generalModel;
|
|
305
|
+
|
|
306
|
+
assignments["code"] = { preferred: bestCoder, fallback: generalModel };
|
|
307
|
+
assignments["debug"] = { preferred: bestReasoning, fallback: fallbackModel };
|
|
308
|
+
assignments["plan"] = { preferred: bestReasoning, fallback: fallbackModel };
|
|
309
|
+
assignments["explore"] = { preferred: bestFast, fallback: generalModel };
|
|
310
|
+
assignments["test"] = { preferred: bestFast, fallback: generalModel };
|
|
311
|
+
assignments["review"] = { preferred: generalModel, fallback: fallbackModel };
|
|
312
|
+
assignments["default"] = { preferred: generalModel, fallback: fallbackModel };
|
|
225
313
|
|
|
226
314
|
return assignments;
|
|
227
315
|
}
|
|
@@ -376,21 +464,32 @@ _Edit this file to customize Phi Code's behavior for your project._
|
|
|
376
464
|
ctx.ui.notify("║ Φ Phi Code Setup Wizard ║", "info");
|
|
377
465
|
ctx.ui.notify("╚══════════════════════════════════════╝\n", "info");
|
|
378
466
|
|
|
379
|
-
// 1. Detect API keys
|
|
380
|
-
ctx.ui.notify("🔍 Detecting
|
|
467
|
+
// 1. Detect API keys and local providers
|
|
468
|
+
ctx.ui.notify("🔍 Detecting providers...", "info");
|
|
381
469
|
const providers = detectProviders();
|
|
470
|
+
|
|
471
|
+
// Probe local providers (Ollama, LM Studio)
|
|
472
|
+
ctx.ui.notify("🔍 Probing local model servers...", "info");
|
|
473
|
+
await detectLocalProviders(providers);
|
|
474
|
+
|
|
382
475
|
const available = providers.filter(p => p.available);
|
|
383
476
|
|
|
384
477
|
if (available.length === 0) {
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
"
|
|
478
|
+
const cloudProviders = providers.filter(p => !p.local);
|
|
479
|
+
ctx.ui.notify("❌ No providers found. Options:\n\n" +
|
|
480
|
+
"**Cloud providers** (set API key):\n" +
|
|
481
|
+
cloudProviders.map(p => ` export ${p.envVar}="your-key" # ${p.name}`).join("\n") +
|
|
482
|
+
"\n\n**Local providers** (start the server):\n" +
|
|
483
|
+
" • Ollama: `ollama serve` (default port 11434)\n" +
|
|
484
|
+
" • LM Studio: Start server in app (default port 1234)\n" +
|
|
485
|
+
"\n💡 Free options: Alibaba Coding Plan (cloud, $0) or Ollama (local, free)", "error");
|
|
388
486
|
return;
|
|
389
487
|
}
|
|
390
488
|
|
|
391
489
|
ctx.ui.notify(`✅ Found ${available.length} provider(s):`, "info");
|
|
392
490
|
for (const p of available) {
|
|
393
|
-
|
|
491
|
+
const tag = p.local ? " (local)" : "";
|
|
492
|
+
ctx.ui.notify(` • ${p.name}${tag} — ${p.models.length} model(s)${p.local ? ": " + p.models.join(", ") : ""}`, "info");
|
|
394
493
|
}
|
|
395
494
|
|
|
396
495
|
const allModels = getAllAvailableModels(providers);
|