@phi-code-admin/phi-code 0.61.0 → 0.61.2

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.
@@ -636,70 +636,33 @@ _Edit this file to customize Phi Code's behavior for your project._
636
636
  async function manualMode(availableModels: string[], ctx: any): Promise<Record<string, { preferred: string; fallback: string }>> {
637
637
  ctx.ui.notify("šŸŽ›ļø Manual mode: assign a model to each task category.\n", "info");
638
638
 
639
- const modelList = availableModels.map((m, i) => ` ${i + 1}. ${m}`).join("\n");
640
- ctx.ui.notify(`Available models:\n${modelList}\n`, "info");
639
+ const modelOptions = ["default (use current model)", ...availableModels];
641
640
  const assignments: Record<string, { preferred: string; fallback: string }> = {};
642
641
 
643
642
  for (const role of TASK_ROLES) {
644
- ctx.ui.notify(`\n**${role.label}** — ${role.desc}\nDefault: ${role.defaultModel}`, "info");
645
- const input = await ctx.ui.input(
646
- `${role.label}`,
647
- `Model name or # (default: ${role.defaultModel})`
643
+ // Primary model selection
644
+ const chosen = await ctx.ui.select(
645
+ `${role.label} — ${role.desc}`,
646
+ modelOptions,
648
647
  );
648
+ const preferredModel = (chosen && chosen !== modelOptions[0]) ? chosen : "default";
649
649
 
650
- let chosen = role.defaultModel;
651
- const trimmed = (input ?? "").trim();
652
-
653
- if (trimmed) {
654
- // Try as number
655
- const num = parseInt(trimmed);
656
- if (num >= 1 && num <= availableModels.length) {
657
- chosen = availableModels[num - 1];
658
- } else {
659
- // Try as model name (partial match)
660
- const match = availableModels.find(m => m.toLowerCase().includes(trimmed.toLowerCase()));
661
- if (match) chosen = match;
662
- }
663
- }
664
-
665
- // Fallback selection
666
- const fallbackDefault = availableModels.find(m => m !== chosen) || chosen;
667
- const fallbackInput = await ctx.ui.input(
650
+ // Fallback model selection
651
+ const fallbackOptions = modelOptions.filter(m => m !== chosen);
652
+ const fallbackChoice = await ctx.ui.select(
668
653
  `Fallback for ${role.label}`,
669
- `Fallback model (default: ${fallbackDefault})`
654
+ fallbackOptions,
670
655
  );
656
+ const fallback = (fallbackChoice && fallbackChoice !== modelOptions[0]) ? fallbackChoice : "default";
671
657
 
672
- let fallback = fallbackDefault;
673
- if ((fallbackInput ?? "").trim()) {
674
- const num = parseInt((fallbackInput ?? "").trim());
675
- if (num >= 1 && num <= availableModels.length) {
676
- fallback = availableModels[num - 1];
677
- } else {
678
- const match = availableModels.find(m => m.toLowerCase().includes((fallbackInput ?? "").trim().toLowerCase()));
679
- if (match) fallback = match;
680
- }
681
- }
682
-
683
- assignments[role.key] = { preferred: chosen, fallback };
684
- ctx.ui.notify(` āœ… ${role.label}: ${chosen} (fallback: ${fallback})`, "info");
658
+ assignments[role.key] = { preferred: preferredModel, fallback };
659
+ ctx.ui.notify(` āœ… ${role.label}: ${preferredModel} (fallback: ${fallback})`, "info");
685
660
  }
686
661
 
687
662
  // Default model
688
- const defaultInput = await ctx.ui.input(
689
- "Default model",
690
- `Model for general tasks (default: ${availableModels[0]})`
691
- );
692
- let defaultModel = availableModels[0];
693
- if ((defaultInput ?? "").trim()) {
694
- const num = parseInt((defaultInput ?? "").trim());
695
- if (num >= 1 && num <= availableModels.length) {
696
- defaultModel = availableModels[num - 1];
697
- } else {
698
- const match = availableModels.find(m => m.toLowerCase().includes((defaultInput ?? "").trim().toLowerCase()));
699
- if (match) defaultModel = match;
700
- }
701
- }
702
- assignments["default"] = { preferred: defaultModel, fallback: availableModels[0] };
663
+ const defaultChoice = await ctx.ui.select("Default model (for general tasks)", modelOptions);
664
+ let defaultModel = (defaultChoice && defaultChoice !== modelOptions[0]) ? defaultChoice : "default";
665
+ assignments["default"] = { preferred: defaultModel, fallback: availableModels[0] || "default" };
703
666
 
704
667
  return assignments;
705
668
  }
@@ -766,15 +729,20 @@ _Edit this file to customize Phi Code's behavior for your project._
766
729
  ctx.ui.notify("\nāš ļø No cloud API keys configured.\n", "warning");
767
730
  }
768
731
 
769
- // Always offer to add a provider
770
- const addProvider = await ctx.ui.input(
771
- "Add/change a provider? (number, or Enter to skip)",
772
- providers.map((p, i) => `${i+1}=${p.name}`).join(", ")
773
- );
774
-
775
- const choiceNum = parseInt(addProvider ?? "0");
776
- if (choiceNum >= 1 && choiceNum <= providers.length) {
777
- const chosen = providers[choiceNum - 1];
732
+ // Always offer to add a provider via select menu
733
+ const providerOptions = [
734
+ "Skip (continue with current providers)",
735
+ ...providers.map(p => {
736
+ const status = p.available ? "āœ…" : "⬜";
737
+ const tag = p.local ? " (local)" : "";
738
+ return `${status} ${p.name}${tag}`;
739
+ }),
740
+ ];
741
+ const addProvider = await ctx.ui.select("Add or change a provider?", providerOptions);
742
+
743
+ const choiceIdx = providerOptions.indexOf(addProvider ?? "");
744
+ if (choiceIdx > 0) { // 0 = Skip
745
+ const chosen = providers[choiceIdx - 1];
778
746
 
779
747
  if (chosen.local) {
780
748
  const port = chosen.name === "Ollama" ? 11434 : 1234;
@@ -844,19 +812,14 @@ _Edit this file to customize Phi Code's behavior for your project._
844
812
  ctx.ui.notify(`\nāœ… **${allModels.length} models** available from ${available.length} provider(s).\n`, "info");
845
813
 
846
814
  // 2. Choose mode
847
- ctx.ui.notify("Choose setup mode:\n" +
848
- " 1. auto — Use optimal defaults (instant)\n" +
849
- " 2. benchmark — Test models first, assign by results (10-15 min)\n" +
850
- " 3. manual — Choose each model yourself\n", "info");
851
-
852
- const modeInput = await ctx.ui.input(
853
- "Setup mode",
854
- "1=auto, 2=benchmark, 3=manual"
855
- );
856
-
857
- const modeStr = (modeInput ?? "").trim().toLowerCase();
858
- const mode = modeStr.startsWith("2") || modeStr.startsWith("b") ? "benchmark"
859
- : modeStr.startsWith("3") || modeStr.startsWith("m") ? "manual"
815
+ const modeOptions = [
816
+ "auto — Use optimal defaults (instant)",
817
+ "benchmark — Test models first, assign by results (10-15 min)",
818
+ "manual — Choose each model yourself",
819
+ ];
820
+ const modeChoice = await ctx.ui.select("Setup mode", modeOptions);
821
+ const mode = (modeChoice ?? "").startsWith("benchmark") ? "benchmark"
822
+ : (modeChoice ?? "").startsWith("manual") ? "manual"
860
823
  : "auto";
861
824
 
862
825
  ctx.ui.notify(`\nšŸ“‹ Mode: **${mode}**\n`, "info");
@@ -661,7 +661,11 @@ ${description}
661
661
  - Typical flow: explore(wave 1) → plan(wave 2) → code(wave 3) → test(wave 4) → review(wave 5)
662
662
  - But independent code tasks can run in parallel within the same wave
663
663
 
664
- 6. **Call the orchestrate tool** with all structured data. It handles execution automatically.`
664
+ 6. **Call the orchestrate tool** with ALL fields in a SINGLE call:
665
+ - title, description, goals, requirements, constraints (project metadata)
666
+ - tasks (array of ALL task objects with title, description, agent, dependencies)
667
+
668
+ āš ļø CRITICAL: Include the \`tasks\` array in the SAME tool call as the project metadata. Do NOT make separate calls. All data must be in ONE orchestrate() invocation.`
665
669
  );
666
670
  },
667
671
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@phi-code-admin/phi-code",
3
- "version": "0.61.0",
3
+ "version": "0.61.2",
4
4
  "description": "Coding agent CLI with read, bash, edit, write tools and session management",
5
5
  "type": "module",
6
6
  "piConfig": {