@actiondock/core 2.0.8 → 2.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@actiondock/core",
3
- "version": "2.0.8",
3
+ "version": "2.0.9",
4
4
  "description": "ActionDock Core Engine - Project loader, runtime execution, SQLite storage, standalone builder, and skill exporter",
5
5
  "type": "module",
6
6
  "main": "./src/index.ts",
@@ -27,7 +27,7 @@
27
27
  "test": "bun test"
28
28
  },
29
29
  "dependencies": {
30
- "@actiondock/sdk": "^2.0.0",
30
+ "@actiondock/sdk": "^2.0.9",
31
31
  "ajv": "^8.17.1",
32
32
  "ajv-formats": "^3.0.1",
33
33
  "yaml": "^2.7.0"
@@ -36,7 +36,13 @@
36
36
  "@types/bun": "latest",
37
37
  "typescript": "^5.7.0"
38
38
  },
39
- "keywords": ["actiondock", "core", "runtime", "storage", "builder"],
39
+ "keywords": [
40
+ "actiondock",
41
+ "core",
42
+ "runtime",
43
+ "storage",
44
+ "builder"
45
+ ],
40
46
  "author": "team4u",
41
47
  "license": "Apache-2.0",
42
48
  "repository": {
@@ -108,10 +108,10 @@ export function initProject(targetDir: string, options: InitOptions = {}): void
108
108
  node: ">=22.12.0",
109
109
  },
110
110
  dependencies: {
111
- "@actiondock/sdk": "^2.0.8",
111
+ "@actiondock/sdk": "^2.0.9",
112
112
  },
113
113
  devDependencies: {
114
- "@actiondock/testing": "^2.0.8",
114
+ "@actiondock/testing": "^2.0.9",
115
115
  "@types/node": "^22.12.0",
116
116
  "tsx": "^4.19.0",
117
117
  "typescript": "^5.7.0",
@@ -1,5 +1,6 @@
1
1
  import { spawnSync } from "node:child_process";
2
2
  import { existsSync, readdirSync, readFileSync, statSync } from "node:fs";
3
+ import { homedir } from "node:os";
3
4
  import { basename, dirname, join, resolve } from "node:path";
4
5
  import { pathToFileURL } from "node:url";
5
6
  import YAML from "yaml";
@@ -80,8 +81,15 @@ export function loadProjectConfig(projectRoot: string): ProjectConfig {
80
81
 
81
82
  /**
82
83
  * 探测宿主系统中可用的包管理工具(优先级:pnpm > npm > yarn > bun)。
84
+ * 可通过环境变量 ACTIONDOCK_INSTALLER 强制指定(如 npm、pnpm、yarn、bun)。
85
+ * 探测必须经 shell 执行:Windows 下 npm/pnpm/yarn 均为 .cmd 垫片,
86
+ * 不经 shell 的 spawnSync 无法解析,将错误地回退到原生 exe 的 bun。
83
87
  */
84
88
  function getInstallCommand(): string[] {
89
+ const preferred = process.env.ACTIONDOCK_INSTALLER?.trim();
90
+ if (preferred) {
91
+ return [preferred, "install"];
92
+ }
85
93
  const candidates: [string, string][] = [
86
94
  ["pnpm", "install"],
87
95
  ["npm", "install"],
@@ -90,8 +98,9 @@ function getInstallCommand(): string[] {
90
98
  ];
91
99
  for (const [pm, action] of candidates) {
92
100
  try {
93
- const check = spawnSync(pm, ["--version"], {
101
+ const check = spawnSync(`${pm} --version`, {
94
102
  stdio: "pipe",
103
+ shell: true,
95
104
  });
96
105
  if (check.status === 0) {
97
106
  return [pm, action];
@@ -103,6 +112,30 @@ function getInstallCommand(): string[] {
103
112
  return ["npm", "install"];
104
113
  }
105
114
 
115
+ /**
116
+ * 解析 npm 风格 .npmrc 中的 strict-ssl 配置(项目级优先于用户级)。
117
+ * 返回 undefined 表示各级配置均未声明该键。
118
+ */
119
+ function resolveNpmStrictSsl(projectRoot: string): boolean | undefined {
120
+ const configPaths = [join(projectRoot, ".npmrc"), join(homedir(), ".npmrc")];
121
+ for (const configPath of configPaths) {
122
+ try {
123
+ if (!existsSync(configPath)) continue;
124
+ const raw = readFileSync(configPath, "utf-8");
125
+ for (const line of raw.split(/\r?\n/)) {
126
+ const matched = line.match(/^\s*strict-ssl\s*=\s*(\S+)\s*$/i);
127
+ if (matched) {
128
+ const falsy = ["false", "0", "no", "off"];
129
+ return !falsy.includes(matched[1].toLowerCase());
130
+ }
131
+ }
132
+ } catch {
133
+ // 配置不可读时继续检查下一级
134
+ }
135
+ }
136
+ return undefined;
137
+ }
138
+
106
139
  /**
107
140
  * 确保项目依赖(node_modules)已正确安装。
108
141
  * 若尚未安装或加载失败时,自动触发包管理器执行依赖安装。
@@ -141,14 +174,30 @@ export function ensureProjectDependencies(projectRoot: string, force = false): b
141
174
  `[actiondock] Installing dependencies using ${installCmd[0]} for '${pkg.name || basename(projectRoot)}'...\n`
142
175
  );
143
176
 
144
- const proc = spawnSync(installCmd[0], installCmd.slice(1), {
177
+ // bun 不读取 .npmrc 的 strict-ssl 配置;当 npm 侧已声明 strict-ssl=false 时,
178
+ // 桥接为 bun 子进程的 NODE_TLS_REJECT_UNAUTHORIZED=0,保证内网自签名证书源下行为一致
179
+ const childEnv = { ...process.env };
180
+ if (installCmd[0] === "bun" && resolveNpmStrictSsl(projectRoot) === false) {
181
+ childEnv.NODE_TLS_REJECT_UNAUTHORIZED = "0";
182
+ }
183
+
184
+ // shell 模式下须传入单一命令字符串;候选命令均来自内置白名单,无注入面
185
+ const proc = spawnSync(installCmd.join(" "), {
145
186
  cwd: projectRoot,
146
187
  stdio: "pipe",
188
+ shell: true,
189
+ env: childEnv,
147
190
  });
148
191
 
149
192
  if (proc.status !== 0) {
150
193
  const errText = proc.stderr?.toString() || `Unknown error during ${installCmd[0]} install`;
151
194
  process.stderr.write(`[actiondock] Warning: Dependency installation failed: ${errText}\n`);
195
+ if (installCmd[0] === "bun" && /SELF_SIGNED_CERT|CERT_|UNABLE_TO_VERIFY|ERR_TLS/i.test(errText)) {
196
+ process.stderr.write(
197
+ `[actiondock] Hint: bun ignores 'strict-ssl=false' from .npmrc. ` +
198
+ `Add 'strict-ssl=false' to the project or user .npmrc, or set ACTIONDOCK_INSTALLER=npm.\n`
199
+ );
200
+ }
152
201
  return false;
153
202
  }
154
203