@anandamw/custom-provider 0.1.7 → 0.1.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.
@@ -528,6 +528,92 @@ async function manageProviders(pi, ctx, configs, options) {
528
528
  }
529
529
  }
530
530
 
531
+ // ── models.json management ───────────────────────────────────────────
532
+
533
+ function modelsPath() {
534
+ return path.join(homedir(), ".pi", "agent", "models.json");
535
+ }
536
+
537
+ function readModels() {
538
+ if (!existsSync(modelsPath())) return { providers: {} };
539
+ try {
540
+ return JSON.parse(readFileSync(modelsPath(), "utf8"));
541
+ } catch {
542
+ return { providers: {} };
543
+ }
544
+ }
545
+
546
+ function writeModels(data) {
547
+ mkdirSync(path.dirname(modelsPath()), { recursive: true });
548
+ writeFileSync(modelsPath(), `${JSON.stringify(data, null, 2)}\n`);
549
+ }
550
+
551
+ function modelsProviderLabel(pid, pdata) {
552
+ const count = Array.isArray(pdata?.models) ? pdata.models.length : 0;
553
+ return `${pid} (${count} model${count !== 1 ? "s" : ""})`;
554
+ }
555
+
556
+ async function manageModelsJSON(pi, ctx) {
557
+ const data = readModels();
558
+ const pids = Object.keys(data.providers);
559
+
560
+ if (pids.length === 0) {
561
+ ctx.ui.notify("No providers in models.json.", "info");
562
+ return;
563
+ }
564
+
565
+ while (true) {
566
+ const selected = await ctx.ui.select(
567
+ "Manage providers in models.json",
568
+ [...pids.map((pid) => modelsProviderLabel(pid, data.providers[pid])), "Back"],
569
+ );
570
+ if (!selected || selected === "Back") return;
571
+
572
+ const pid = pids.find((id) => selected.startsWith(id));
573
+ if (!pid) continue;
574
+ const provider = data.providers[pid];
575
+ const models = Array.isArray(provider?.models) ? provider.models : [];
576
+
577
+ const action = await ctx.ui.select(`Manage provider "${pid}"`, [
578
+ "Delete entire provider",
579
+ "Delete individual models",
580
+ "Back",
581
+ ]);
582
+ if (action === "Delete entire provider") {
583
+ const confirm = await ctx.ui.confirm(
584
+ `Delete provider "${pid}" and all ${models.length} model(s)?`,
585
+ );
586
+ if (confirm) {
587
+ delete data.providers[pid];
588
+ writeModels(data);
589
+ ctx.ui.notify(`Deleted provider "${pid}". Reload Pi to apply.`, "info");
590
+ return;
591
+ }
592
+ } else if (action === "Delete individual models") {
593
+ if (models.length === 0) {
594
+ ctx.ui.notify("No models in this provider.", "info");
595
+ continue;
596
+ }
597
+ const mid = await ctx.ui.select(
598
+ "Select model to delete",
599
+ [...models.map((m) => m.id), "Back"],
600
+ );
601
+ if (!mid || mid === "Back") continue;
602
+ const confirm = await ctx.ui.confirm(`Delete model "${mid}"?`);
603
+ if (confirm) {
604
+ provider.models = models.filter((m) => m.id !== mid);
605
+ if (provider.models.length === 0) {
606
+ // ponytail: prompt to also delete empty provider, add when users complain
607
+ }
608
+ writeModels(data);
609
+ ctx.ui.notify(`Deleted model "${mid}". Reload Pi to apply.`, "info");
610
+ }
611
+ }
612
+ }
613
+ }
614
+
615
+ // ── main extension ────────────────────────────────────────────────────
616
+
531
617
  export default function customProvider(pi, options = {}) {
532
618
  const { providerId, config } = buildProviderRegistration();
533
619
  pi.registerProvider(providerId, config);
@@ -592,4 +678,15 @@ export default function customProvider(pi, options = {}) {
592
678
  await selectAvailableProvider(pi, ctx, choice.id);
593
679
  },
594
680
  });
681
+
682
+ pi.registerCommand("models", {
683
+ description: "Delete providers and models from models.json",
684
+ handler: async (_args, ctx) => {
685
+ if (!ctx.hasUI) {
686
+ ctx.ui.notify("/models requires an interactive UI.", "error");
687
+ return;
688
+ }
689
+ await manageModelsJSON(pi, ctx);
690
+ },
691
+ });
595
692
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@anandamw/custom-provider",
3
- "version": "0.1.7",
3
+ "version": "0.1.8",
4
4
  "description": "Configurable OpenAI-compatible custom provider for Pi",
5
5
  "type": "module",
6
6
  "private": false,