moflo 4.8.71 → 4.8.73
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": "moflo",
|
|
3
|
-
"version": "4.8.
|
|
3
|
+
"version": "4.8.73",
|
|
4
4
|
"description": "MoFlo — AI agent orchestration for Claude Code. Forked from ruflo/claude-flow with patches applied to source, plus feature-level orchestration.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -112,7 +112,7 @@
|
|
|
112
112
|
"@types/js-yaml": "^4.0.9",
|
|
113
113
|
"@types/node": "^20.19.37",
|
|
114
114
|
"eslint": "^8.0.0",
|
|
115
|
-
"moflo": "^4.8.
|
|
115
|
+
"moflo": "^4.8.72",
|
|
116
116
|
"tsx": "^4.21.0",
|
|
117
117
|
"typescript": "^5.9.3",
|
|
118
118
|
"vitest": "^4.0.0"
|
|
@@ -15,12 +15,13 @@ import { execSync } from 'node:child_process';
|
|
|
15
15
|
import { existsSync, readFileSync } from 'node:fs';
|
|
16
16
|
import { platform } from 'node:os';
|
|
17
17
|
import { join } from 'node:path';
|
|
18
|
+
import { escapeShellArg } from './shell.js';
|
|
18
19
|
export const DEFAULT_SANDBOX_CONFIG = {
|
|
19
20
|
enabled: false,
|
|
20
21
|
tier: 'auto',
|
|
21
22
|
};
|
|
22
23
|
/** Recommended image for first-time Windows Docker sandbox setup. */
|
|
23
|
-
export const RECOMMENDED_DOCKER_IMAGE = 'node:20-bookworm
|
|
24
|
+
export const RECOMMENDED_DOCKER_IMAGE = 'node:20-bookworm';
|
|
24
25
|
// ============================================================================
|
|
25
26
|
// Detection (cached)
|
|
26
27
|
// ============================================================================
|
|
@@ -40,6 +41,7 @@ export function detectSandboxCapability() {
|
|
|
40
41
|
/** Reset the cached result (for testing). */
|
|
41
42
|
export function resetSandboxCache() {
|
|
42
43
|
_cached = undefined;
|
|
44
|
+
_imageExistsCache.clear();
|
|
43
45
|
}
|
|
44
46
|
function detectUncached() {
|
|
45
47
|
const os = platform();
|
|
@@ -165,32 +167,33 @@ export async function loadSandboxConfigFromProject(projectRoot) {
|
|
|
165
167
|
* @throws Error if tier is 'full' but no OS sandbox is available.
|
|
166
168
|
*/
|
|
167
169
|
export function resolveEffectiveSandbox(config, capability = detectSandboxCapability()) {
|
|
170
|
+
let resolved = config;
|
|
168
171
|
// Config disabled or tier is denylist-only => no OS sandbox
|
|
169
|
-
if (!
|
|
172
|
+
if (!resolved.enabled || resolved.tier === 'denylist-only') {
|
|
170
173
|
return {
|
|
171
174
|
useOsSandbox: false,
|
|
172
175
|
capability,
|
|
173
|
-
config,
|
|
176
|
+
config: resolved,
|
|
174
177
|
displayStatus: `OS sandbox: disabled (denylist active)`,
|
|
175
178
|
};
|
|
176
179
|
}
|
|
177
|
-
// Windows:
|
|
178
|
-
//
|
|
179
|
-
//
|
|
180
|
-
// "not available (win32)" message.
|
|
180
|
+
// Windows: Docker is required for OS sandboxing. If Docker is available,
|
|
181
|
+
// auto-default the image and auto-pull it on first use so the user doesn't
|
|
182
|
+
// have to do manual setup. Only throw if Docker itself isn't installed/running.
|
|
181
183
|
if (capability.platform === 'win32') {
|
|
182
184
|
if (!capability.available) {
|
|
183
185
|
throw new Error(formatWindowsDockerNotReadyMessage());
|
|
184
186
|
}
|
|
185
|
-
|
|
186
|
-
|
|
187
|
+
const image = resolved.dockerImage || RECOMMENDED_DOCKER_IMAGE;
|
|
188
|
+
if (!resolved.dockerImage) {
|
|
189
|
+
resolved = { ...resolved, dockerImage: image };
|
|
187
190
|
}
|
|
188
|
-
if (!dockerImageExists(
|
|
189
|
-
|
|
191
|
+
if (!dockerImageExists(image)) {
|
|
192
|
+
dockerPullImage(image);
|
|
190
193
|
}
|
|
191
194
|
}
|
|
192
195
|
// tier: full — require OS sandbox on non-Windows platforms
|
|
193
|
-
if (
|
|
196
|
+
if (resolved.tier === 'full' && !capability.available) {
|
|
194
197
|
throw new Error(`Sandbox tier "full" requires an OS sandbox but none was detected on ${capability.platform}. ` +
|
|
195
198
|
`Install bubblewrap (Linux) or set sandbox.tier to "auto".`);
|
|
196
199
|
}
|
|
@@ -198,33 +201,51 @@ export function resolveEffectiveSandbox(config, capability = detectSandboxCapabi
|
|
|
198
201
|
return {
|
|
199
202
|
useOsSandbox: false,
|
|
200
203
|
capability,
|
|
201
|
-
config,
|
|
204
|
+
config: resolved,
|
|
202
205
|
displayStatus: `OS sandbox: not available (${capability.platform})`,
|
|
203
206
|
};
|
|
204
207
|
}
|
|
205
208
|
return {
|
|
206
209
|
useOsSandbox: true,
|
|
207
210
|
capability,
|
|
208
|
-
config,
|
|
211
|
+
config: resolved,
|
|
209
212
|
displayStatus: `OS sandbox: ${capability.tool} (${capability.platform})`,
|
|
210
213
|
};
|
|
211
214
|
}
|
|
215
|
+
const _imageExistsCache = new Map();
|
|
212
216
|
/**
|
|
213
217
|
* Check whether a Docker image is available locally (already pulled).
|
|
214
|
-
*
|
|
218
|
+
* Result is cached per image name for the process lifetime.
|
|
215
219
|
*/
|
|
216
220
|
function dockerImageExists(image) {
|
|
221
|
+
const cached = _imageExistsCache.get(image);
|
|
222
|
+
if (cached !== undefined)
|
|
223
|
+
return cached;
|
|
217
224
|
try {
|
|
218
|
-
execSync(`docker image inspect ${
|
|
225
|
+
execSync(`docker image inspect ${escapeShellArg(image)}`, { stdio: 'ignore', timeout: 5000 });
|
|
226
|
+
_imageExistsCache.set(image, true);
|
|
219
227
|
return true;
|
|
220
228
|
}
|
|
221
229
|
catch {
|
|
222
230
|
return false;
|
|
223
231
|
}
|
|
224
232
|
}
|
|
225
|
-
/**
|
|
226
|
-
|
|
227
|
-
|
|
233
|
+
/**
|
|
234
|
+
* Pull a Docker image, printing a one-time setup banner so the user knows
|
|
235
|
+
* what's happening and why. Throws if the pull fails.
|
|
236
|
+
*/
|
|
237
|
+
function dockerPullImage(image) {
|
|
238
|
+
console.log(`[spell] One-time setup: pulling Docker image ${image} for sandboxing...\n` +
|
|
239
|
+
` This only happens once — Docker caches the image afterwards.`);
|
|
240
|
+
try {
|
|
241
|
+
execSync(`docker pull ${escapeShellArg(image)}`, { stdio: 'inherit', timeout: 300_000 });
|
|
242
|
+
_imageExistsCache.set(image, true);
|
|
243
|
+
console.log(`[spell] Docker image ${image} is ready.`);
|
|
244
|
+
}
|
|
245
|
+
catch {
|
|
246
|
+
throw new Error(`Failed to pull Docker image "${image}".\n\n` +
|
|
247
|
+
'Make sure Docker Desktop is running and you have internet access, then try again.');
|
|
248
|
+
}
|
|
228
249
|
}
|
|
229
250
|
// ── Beginner-friendly setup messages (Windows) ──────────────────────────
|
|
230
251
|
function formatWindowsDockerNotReadyMessage() {
|
|
@@ -241,51 +262,13 @@ function formatWindowsDockerNotReadyMessage() {
|
|
|
241
262
|
' Wait for the whale icon in your system tray to stop animating —',
|
|
242
263
|
' that means Docker is ready.',
|
|
243
264
|
'',
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
'',
|
|
247
|
-
' 4. Add this to your moflo.yaml:',
|
|
248
|
-
' sandbox:',
|
|
249
|
-
' enabled: true',
|
|
250
|
-
` dockerImage: ${RECOMMENDED_DOCKER_IMAGE}`,
|
|
265
|
+
`MoFlo will auto-pull the default image (${RECOMMENDED_DOCKER_IMAGE}) on`,
|
|
266
|
+
'the first spell run.',
|
|
251
267
|
'',
|
|
252
|
-
'Not ready to set this up?
|
|
268
|
+
'Not ready to set this up? Turn sandboxing off by setting',
|
|
253
269
|
'`sandbox.enabled: false` in moflo.yaml.',
|
|
254
270
|
].join('\n');
|
|
255
271
|
}
|
|
256
|
-
function formatWindowsDockerImageMissingMessage() {
|
|
257
|
-
return [
|
|
258
|
-
'Sandboxing is enabled, but no Docker image is configured.',
|
|
259
|
-
'',
|
|
260
|
-
'Docker is ready on this machine — it just needs to know which image to',
|
|
261
|
-
'run your spell steps inside. This is a one-time setup:',
|
|
262
|
-
'',
|
|
263
|
-
' 1. Open PowerShell (or any terminal) and pull the recommended image:',
|
|
264
|
-
` docker pull ${RECOMMENDED_DOCKER_IMAGE}`,
|
|
265
|
-
'',
|
|
266
|
-
' 2. Add this to your moflo.yaml:',
|
|
267
|
-
' sandbox:',
|
|
268
|
-
' enabled: true',
|
|
269
|
-
` dockerImage: ${RECOMMENDED_DOCKER_IMAGE}`,
|
|
270
|
-
'',
|
|
271
|
-
`The recommended image (${RECOMMENDED_DOCKER_IMAGE}) includes node, npm,`,
|
|
272
|
-
'bash, git, and curl. Any image with bash will work.',
|
|
273
|
-
].join('\n');
|
|
274
|
-
}
|
|
275
|
-
function formatWindowsDockerImageNotPulledMessage(image) {
|
|
276
|
-
return [
|
|
277
|
-
`Sandboxing is enabled, but the Docker image "${image}" is not available`,
|
|
278
|
-
'on this machine yet.',
|
|
279
|
-
'',
|
|
280
|
-
'To fix this, open PowerShell (or any terminal) and run:',
|
|
281
|
-
` docker pull ${image}`,
|
|
282
|
-
'',
|
|
283
|
-
'This only needs to happen once — Docker caches the image afterwards.',
|
|
284
|
-
'',
|
|
285
|
-
'If Docker Desktop is not running, start it from the Start menu first',
|
|
286
|
-
'and wait for the whale icon in your system tray to stop animating.',
|
|
287
|
-
].join('\n');
|
|
288
|
-
}
|
|
289
272
|
/**
|
|
290
273
|
* Format a one-line log message for spell startup.
|
|
291
274
|
*/
|