opencode-hub 1.0.8 → 1.0.9

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 (3) hide show
  1. package/oc-tui.js +39 -4
  2. package/package.json +1 -1
  3. package/plugin.js +14 -2
package/oc-tui.js CHANGED
@@ -34,7 +34,15 @@ function loadNpmPlugins() {
34
34
  var name = p.replace(/@[^@\/]+$/, "") || p;
35
35
  var version = "";
36
36
  try {
37
+ // First try config-local node_modules, then global npm node_modules
37
38
  var pkgPath = join(CONFIG_DIR, "node_modules", name, "package.json");
39
+ if (!existsSync(pkgPath)) {
40
+ // Global npm fallback (Windows: AppData/Roaming/npm/node_modules, Unix: prefix/lib/node_modules)
41
+ var globalNpm = process.platform === "win32"
42
+ ? join(homedir(), "AppData", "Roaming", "npm", "node_modules")
43
+ : join("/usr", "lib", "node_modules");
44
+ pkgPath = join(globalNpm, name, "package.json");
45
+ }
38
46
  if (existsSync(pkgPath)) {
39
47
  version = JSON.parse(readFileSync(pkgPath, "utf-8")).version || "";
40
48
  }
@@ -427,7 +435,8 @@ function getPluginActions(pitem) {
427
435
  } else {
428
436
  a.push({ key: "enable-auto", label: "Enable auto-update" });
429
437
  }
430
- a.push({ key: "force-update", label: "Force rebuild & deploy" });
438
+ a.push({ key: "update", label: "Force rebuild & deploy" });
439
+ a.push({ key: "update-all", label: "Update all plugins" });
431
440
  a.push({ key: "commits", label: "Select specific commit (Downgrade)" });
432
441
  a.push({ key: "disable-plugin", label: "Disable plugin" });
433
442
  a.push({ key: "cancel", label: "Cancel" });
@@ -779,9 +788,9 @@ function buildPlugins(pushBody, pushFoot, cols, barW) {
779
788
  } else {
780
789
  pushFoot(" " + DIM + "^v" + RST + "/" + DIM + "WS" + RST + " Move " +
781
790
  DIM + "Enter" + RST + " Select " +
782
- DIM + "F" + RST + " Fetch " +
783
- DIM + "A" + RST + " Toggle auto " +
784
791
  DIM + "U" + RST + " Update " +
792
+ DIM + "D" + RST + " Disable " +
793
+ DIM + "A" + RST + " Toggle auto " +
785
794
  DIM + "Q" + RST + " Quit" + RST);
786
795
  }
787
796
  }
@@ -970,6 +979,19 @@ function handlePluginKey(key) {
970
979
  flash(err ? p.name + ": " + err : p.name + " updated. Restart OpenCode to apply.");
971
980
  }
972
981
  }
982
+ else if (key === "d") {
983
+ if (pluginItems.length > 0) {
984
+ var p = pluginItems[pcursor];
985
+ var plugins = loadPlugins();
986
+ var match = plugins.find(function(r) { return r.name === p.name; });
987
+ if (match) { match.enabled = false; savePlugins(plugins); }
988
+ var deployedPath = join(PLUGINS_DIR, p.pluginFile);
989
+ if (existsSync(deployedPath)) { try { unlinkSync(deployedPath); } catch {} }
990
+ pluginItems = buildPluginList();
991
+ if (pcursor >= pluginItems.length) pcursor = Math.max(0, pluginItems.length - 1);
992
+ flash(p.name + " disabled. Restart OpenCode to unload.");
993
+ }
994
+ }
973
995
  else if (key === "q" || key === "escape") { cleanup(); process.exit(1); }
974
996
  } else if (mode === "pactions") {
975
997
  var pitem = pluginItems[pcursor];
@@ -978,7 +1000,7 @@ function handlePluginKey(key) {
978
1000
  else if (key === "down" || key === "s") { pacursor = Math.min(acts.length - 1, pacursor + 1); }
979
1001
  else if (key === "enter" || key === "space") {
980
1002
  var action = acts[pacursor].key;
981
- if (action === "update" || action === "force-update") {
1003
+ if (action === "update") {
982
1004
  flash("Updating " + pitem.name + "...");
983
1005
  render();
984
1006
  var err = runPluginUpdate(pitem);
@@ -987,6 +1009,19 @@ function handlePluginKey(key) {
987
1009
  flash(err ? pitem.name + ": " + err : pitem.name + " updated. Restart OpenCode to apply.");
988
1010
  mode = "list";
989
1011
  }
1012
+ else if (action === "update-all") {
1013
+ var errors = [];
1014
+ for (var pi of pluginItems) {
1015
+ flash("Updating " + pi.name + "...");
1016
+ render();
1017
+ var e = runPluginUpdate(pi);
1018
+ if (e) errors.push(pi.name + ": " + e);
1019
+ }
1020
+ pluginItems = buildPluginList();
1021
+ if (pcursor >= pluginItems.length) pcursor = Math.max(0, pluginItems.length - 1);
1022
+ flash(errors.length > 0 ? errors.join("; ") : "All plugins updated. Restart OpenCode to apply.");
1023
+ mode = "list";
1024
+ }
990
1025
  else if (action === "enable-auto" || action === "disable-auto") {
991
1026
  var newVal = action === "enable-auto";
992
1027
  pitem.autoUpdate = newVal;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-hub",
3
- "version": "1.0.8",
3
+ "version": "1.0.9",
4
4
  "description": "TUI launcher for OpenCode - project switcher and plugin manager with oc command",
5
5
  "main": "plugin.js",
6
6
  "type": "module",
package/plugin.js CHANGED
@@ -12,10 +12,10 @@ function findTuiScript() {
12
12
  var sameDirPath = join(import.meta.dir, "oc-tui.js");
13
13
  if (existsSync(sameDirPath)) return sameDirPath;
14
14
 
15
- // 2. Find config dir, then check repos/intisy/opencode-launcher/ (updater case)
15
+ // 2. Find config dir, then check repos/intisy/opencode-hub/ (updater case)
16
16
  var configDir = findConfigDir(import.meta.dir);
17
17
  if (configDir) {
18
- var repoPath = join(configDir, "repos", "intisy", "opencode-launcher", "oc-tui.js");
18
+ var repoPath = join(configDir, "repos", "intisy", "opencode-hub", "oc-tui.js");
19
19
  if (existsSync(repoPath)) return repoPath;
20
20
  }
21
21
 
@@ -52,6 +52,18 @@ function installOcCommand() {
52
52
  var binDir = getBinDir();
53
53
  if (!existsSync(binDir)) try { mkdirSync(binDir, { recursive: true }); } catch {}
54
54
 
55
+ // Always keep binDir/oc-tui.js in sync with the source (so `oc` always runs latest)
56
+ var binTuiPath = join(binDir, "oc-tui.js");
57
+ try {
58
+ var srcContent = readFileSync(tuiPath, "utf-8");
59
+ var dstContent = existsSync(binTuiPath) ? readFileSync(binTuiPath, "utf-8") : null;
60
+ if (srcContent !== dstContent) {
61
+ writeFileSync(binTuiPath, srcContent, "utf-8");
62
+ }
63
+ } catch {}
64
+ // Point shell launchers at the stable binDir copy
65
+ tuiPath = binTuiPath;
66
+
55
67
  var tuiPathEscaped = tuiPath.replace(/\\/g, "\\\\");
56
68
 
57
69
  if (process.platform === "win32") {