File size: 2,052 Bytes
c1243f9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
import path from "node:path";
import type { PluginRecord } from "./registry.js";
import { resolveConfigDir, shortenHomeInString } from "../utils.js";
import { resolveBundledPluginsDir } from "./bundled-dir.js";

export type PluginSourceRoots = {
  stock?: string;
  global?: string;
  workspace?: string;
};

function tryRelative(root: string, filePath: string): string | null {
  const rel = path.relative(root, filePath);
  if (!rel || rel === ".") {
    return null;
  }
  if (rel === "..") {
    return null;
  }
  if (rel.startsWith(`..${path.sep}`) || rel.startsWith("../") || rel.startsWith("..\\")) {
    return null;
  }
  if (path.isAbsolute(rel)) {
    return null;
  }
  // Normalize to forward slashes for display (path.relative uses backslashes on Windows)
  return rel.replaceAll("\\", "/");
}

export function resolvePluginSourceRoots(params: { workspaceDir?: string }): PluginSourceRoots {
  const stock = resolveBundledPluginsDir();
  const global = path.join(resolveConfigDir(), "extensions");
  const workspace = params.workspaceDir
    ? path.join(params.workspaceDir, ".openclaw", "extensions")
    : undefined;
  return { stock, global, workspace };
}

export function formatPluginSourceForTable(
  plugin: Pick<PluginRecord, "source" | "origin">,
  roots: PluginSourceRoots,
): { value: string; rootKey?: keyof PluginSourceRoots } {
  const raw = plugin.source;

  if (plugin.origin === "bundled" && roots.stock) {
    const rel = tryRelative(roots.stock, raw);
    if (rel) {
      return { value: `stock:${rel}`, rootKey: "stock" };
    }
  }
  if (plugin.origin === "workspace" && roots.workspace) {
    const rel = tryRelative(roots.workspace, raw);
    if (rel) {
      return { value: `workspace:${rel}`, rootKey: "workspace" };
    }
  }
  if (plugin.origin === "global" && roots.global) {
    const rel = tryRelative(roots.global, raw);
    if (rel) {
      return { value: `global:${rel}`, rootKey: "global" };
    }
  }

  // Keep this stable/pasteable; only ~-shorten.
  return { value: shortenHomeInString(raw) };
}