Skip to content

Commit 62767aa

Browse files
committed
fix: resolve npx install dependencies
1 parent 4c8868d commit 62767aa

7 files changed

Lines changed: 124 additions & 34 deletions

File tree

README.md

Lines changed: 3 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ AiToEarn 社交媒体管理工具的 OpenClaw 插件。
55
## 一键安装
66

77
```bash
8-
npx @aitoearn/openclaw-plugin
8+
npx -y @aitoearn/openclaw-plugin
99
```
1010

1111
这个命令会自动:
@@ -15,19 +15,6 @@ npx @aitoearn/openclaw-plugin
1515
3. 验证连通性
1616
4. 写入 `plugins.entries.aitoearn.config`
1717

18-
兼容别名:
19-
20-
```bash
21-
npx @aitoearn/openclaw-plugin install
22-
npx @aitoearn/openclaw-plugin setup
23-
```
24-
25-
## 标准安装
26-
27-
```bash
28-
openclaw plugins install @aitoearn/openclaw-plugin
29-
```
30-
3118
## 手动配置
3219

3320
```bash
@@ -52,16 +39,10 @@ openclaw config set plugins.entries.aitoearn.config.apiKey \
5239
3. 点击左侧菜单 **设置**
5340
4.**API Key** 中点击创建,复制生成的 Key
5441

55-
## 兼容命令
56-
57-
```bash
58-
openclaw aitoearn setup
59-
```
60-
61-
这条命令仍可用,但后续推荐优先使用:
42+
如果你的 npm 版本会在首次执行时提示确认安装包,统一使用:
6243

6344
```bash
64-
npx @aitoearn/openclaw-plugin
45+
npx -y @aitoearn/openclaw-plugin
6546
```
6647

6748
完成配置后,重启 Gateway:

openclaw.plugin.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"id": "aitoearn",
33
"name": "AiToEarn",
44
"description": "AiToEarn social media management tools",
5-
"version": "1.0.3",
5+
"version": "1.0.4",
66
"configSchema": {
77
"type": "object",
88
"additionalProperties": false,

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@aitoearn/openclaw-plugin",
3-
"version": "1.0.3",
3+
"version": "1.0.4",
44
"type": "module",
55
"main": "./dist/index.js",
66
"types": "./dist/index.d.ts",

src/cli.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,14 +39,12 @@ interface CliDependencies {
3939
runSetupFlow: (options?: { showIntro?: boolean }) => Promise<SetupFlowResult>;
4040
}
4141

42-
const HELP_TEXT = `Usage: npx @aitoearn/openclaw-plugin [install|setup]
42+
const HELP_TEXT = `Usage: npx -y @aitoearn/openclaw-plugin
4343
4444
Bootstrap installer for the AiToEarn OpenClaw plugin.
4545
4646
Examples:
47-
npx @aitoearn/openclaw-plugin
48-
npx @aitoearn/openclaw-plugin install
49-
npx @aitoearn/openclaw-plugin setup`;
47+
npx -y @aitoearn/openclaw-plugin`;
5048

5149
export async function runSetupCli(
5250
args: string[],

src/openclaw-bootstrap.test.ts

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,95 @@ describe("openclaw-bootstrap", () => {
212212
)
213213
).toContain("module.exports");
214214
});
215+
216+
it("installs scoped dependencies without resolving their runtime entrypoint", async () => {
217+
const packageRoot = await mkTempDir();
218+
const homeDir = await mkTempDir();
219+
const env = { OPENCLAW_STATE_DIR: path.join(homeDir, ".openclaw") };
220+
221+
await mkdir(path.join(packageRoot, "dist"), { recursive: true });
222+
await writeFile(
223+
path.join(packageRoot, "package.json"),
224+
JSON.stringify(
225+
{
226+
name: "@aitoearn/openclaw-plugin",
227+
version: "1.2.3",
228+
files: ["dist", "openclaw.plugin.json"],
229+
dependencies: {
230+
"@scope/dep-a": "1.0.0",
231+
},
232+
},
233+
null,
234+
2
235+
),
236+
"utf8"
237+
);
238+
await writeFile(path.join(packageRoot, "dist", "index.js"), "export {};\n", "utf8");
239+
await writeFile(path.join(packageRoot, "openclaw.plugin.json"), "{}\n", "utf8");
240+
241+
const scopedDependencyRoot = path.join(
242+
packageRoot,
243+
"node_modules",
244+
"@scope",
245+
"dep-a"
246+
);
247+
await mkdir(path.join(scopedDependencyRoot, "dist", "esm"), { recursive: true });
248+
await writeFile(
249+
path.join(scopedDependencyRoot, "package.json"),
250+
JSON.stringify(
251+
{
252+
name: "@scope/dep-a",
253+
version: "1.0.0",
254+
type: "module",
255+
exports: {
256+
".": {
257+
import: "./dist/esm/index.js",
258+
require: "./dist/cjs/index.js",
259+
},
260+
},
261+
},
262+
null,
263+
2
264+
),
265+
"utf8"
266+
);
267+
await writeFile(
268+
path.join(scopedDependencyRoot, "dist", "esm", "index.js"),
269+
"export const ok = true;\n",
270+
"utf8"
271+
);
272+
273+
const result = await installPackageIntoOpenClaw(
274+
{
275+
rootDir: packageRoot,
276+
manifest: {
277+
name: "@aitoearn/openclaw-plugin",
278+
version: "1.2.3",
279+
files: ["dist", "openclaw.plugin.json"],
280+
dependencies: {
281+
"@scope/dep-a": "1.0.0",
282+
},
283+
},
284+
} satisfies PackageContext,
285+
env,
286+
() => homeDir
287+
);
288+
289+
expect(
290+
await readFile(
291+
path.join(
292+
result.targetDir,
293+
"node_modules",
294+
"@scope",
295+
"dep-a",
296+
"dist",
297+
"esm",
298+
"index.js"
299+
),
300+
"utf8"
301+
)
302+
).toContain("ok = true");
303+
});
215304
});
216305

217306
async function mkTempDir(): Promise<string> {

src/openclaw-bootstrap.ts

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import { createRequire } from "node:module";
21
import { existsSync } from "node:fs";
32
import {
43
cp,
@@ -289,9 +288,16 @@ async function resolveDependencyRoot(
289288
dependencyName: string,
290289
requesterDir: string
291290
): Promise<string> {
292-
const requireFromRequester = createRequire(path.join(requesterDir, "package.json"));
293-
const resolvedEntry = requireFromRequester.resolve(dependencyName);
294-
return await findPackageRoot(path.dirname(resolvedEntry));
291+
for (const nodeModulesDir of resolveNodeModulesSearchDirs(requesterDir)) {
292+
const dependencyRoot = path.join(nodeModulesDir, dependencyName);
293+
if (await pathExists(path.join(dependencyRoot, "package.json"))) {
294+
return dependencyRoot;
295+
}
296+
}
297+
298+
throw new Error(
299+
`Could not locate installed package "${dependencyName}" from ${requesterDir}`
300+
);
295301
}
296302

297303
function resolveDependencyRelativePath(dependencyRoot: string): string {
@@ -321,6 +327,22 @@ function findOutermostNodeModulesDir(startPath: string): string | null {
321327
}
322328
}
323329

330+
function resolveNodeModulesSearchDirs(startDir: string): string[] {
331+
const results: string[] = [];
332+
let current = path.resolve(startDir);
333+
334+
while (true) {
335+
results.push(path.join(current, "node_modules"));
336+
337+
const parent = path.dirname(current);
338+
if (parent === current) {
339+
return results;
340+
}
341+
342+
current = parent;
343+
}
344+
}
345+
324346
async function findPackageRoot(startDir: string): Promise<string> {
325347
let current = path.resolve(startDir);
326348

0 commit comments

Comments
 (0)