moflo 4.8.87-rc.2 → 4.8.87-rc.3

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.87-rc.2",
3
+ "version": "4.8.87-rc.3",
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",
@@ -114,7 +114,7 @@
114
114
  "@typescript-eslint/eslint-plugin": "^7.18.0",
115
115
  "@typescript-eslint/parser": "^7.18.0",
116
116
  "eslint": "^8.0.0",
117
- "moflo": "^4.8.87-rc.1",
117
+ "moflo": "^4.8.87-rc.2",
118
118
  "tsx": "^4.21.0",
119
119
  "typescript": "^5.9.3",
120
120
  "vitest": "^4.0.0"
@@ -4,6 +4,7 @@
4
4
  */
5
5
  import { mkdirSync, writeFileSync, existsSync, readFileSync, statSync, readdirSync } from 'fs';
6
6
  import { dirname, join, resolve, extname } from 'path';
7
+ import { requireMofloOrWarn } from '../services/moflo-require.js';
7
8
  // Real vector search functions - lazy loaded to avoid circular imports
8
9
  let searchEntriesFn = null;
9
10
  async function getRealSearchFunction() {
@@ -94,8 +95,12 @@ let embeddingService = null;
94
95
  async function getEmbeddingService() {
95
96
  if (embeddingService)
96
97
  return embeddingService;
97
- const { createEmbeddingService } = await import('@moflo/embeddings');
98
- embeddingService = createEmbeddingService({ provider: 'fastembed' });
98
+ const mod = await requireMofloOrWarn('@moflo/embeddings', ['createEmbeddingService'], {
99
+ tag: 'hooks-tools',
100
+ consequence: 'routing/attention require fastembed and have nothing to fall back to.',
101
+ throwIfMissing: true,
102
+ });
103
+ embeddingService = mod.createEmbeddingService({ provider: 'fastembed' });
99
104
  return embeddingService;
100
105
  }
101
106
  async function embedTexts(texts) {
@@ -13,12 +13,16 @@
13
13
  */
14
14
  import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'node:fs';
15
15
  import { join } from 'node:path';
16
- // Try to import real embeddings from @moflo/embeddings (auto-selects best provider)
16
+ import { requireMofloOrWarn } from '../services/moflo-require.js';
17
17
  let realEmbeddings = null;
18
18
  let embeddingServiceName = 'none';
19
19
  try {
20
- const embeddingsModule = await import('@moflo/embeddings').catch(() => null);
21
- if (embeddingsModule?.createEmbeddingServiceAsync) {
20
+ const embeddingsModule = await requireMofloOrWarn('@moflo/embeddings', ['createEmbeddingServiceAsync'], {
21
+ tag: 'neural-tools',
22
+ consequence: 'neural_predict / neural_patterns will fall back to deterministic-hash embeddings, ' +
23
+ 'which is not allowed in production.',
24
+ });
25
+ if (embeddingsModule) {
22
26
  const service = await embeddingsModule.createEmbeddingServiceAsync({
23
27
  provider: 'auto',
24
28
  autoInstall: false,
@@ -32,8 +36,8 @@ try {
32
36
  embeddingServiceName = `@moflo/embeddings (${service.provider})`;
33
37
  }
34
38
  }
35
- catch {
36
- // No embedding provider available, will use fallback
39
+ catch (err) {
40
+ process.stderr.write(`[neural-tools] @moflo/embeddings load failed: ${err instanceof Error ? err.message : String(err)}\n`);
37
41
  }
38
42
  // Storage paths
39
43
  const STORAGE_DIR = '.claude-flow';
@@ -378,8 +378,13 @@ const aidefenceIsSafeTool = {
378
378
  handler: async (args) => {
379
379
  const input = args.input;
380
380
  try {
381
- const { isSafe } = await import('@moflo/aidefence');
382
- const safe = isSafe(input);
381
+ // Route through getAIDefence() so this tool inherits the same auto-install
382
+ // fallback as every other aidefence handler in this file. A bare
383
+ // `import('@moflo/aidefence')` skips that path and surfaces a hard
384
+ // ERR_MODULE_NOT_FOUND when the package isn't resolvable.
385
+ const defender = await getAIDefence();
386
+ const result = defender.quickScan(input);
387
+ const safe = !result.threat;
383
388
  return {
384
389
  content: [{
385
390
  type: 'text',
@@ -14,7 +14,7 @@
14
14
  * @module @moflo/cli/services/embeddings-migration
15
15
  */
16
16
  /* eslint-disable @typescript-eslint/no-explicit-any */
17
- import { mofloImport } from './moflo-require.js';
17
+ import { mofloImport, requireMofloOrWarn } from './moflo-require.js';
18
18
  import { atomicWriteFileSync } from './atomic-file-write.js';
19
19
  /**
20
20
  * Run the migration if and only if it's needed.
@@ -31,13 +31,12 @@ export async function runEmbeddingsMigrationIfNeeded(options = {}) {
31
31
  const dbPath = path.resolve(options.dbPath ?? path.join(process.cwd(), '.swarm', 'memory.db'));
32
32
  if (!fs.existsSync(dbPath))
33
33
  return false;
34
- let embeddings;
35
- try {
36
- embeddings = await import('@moflo/embeddings');
37
- }
38
- catch {
34
+ const embeddings = await requireMofloOrWarn('@moflo/embeddings', ['EMBEDDINGS_VERSION', 'createEmbeddingService', 'runUpgrade'], {
35
+ tag: 'embeddings-migration',
36
+ consequence: 'migration skipped; memory.db will keep its current embeddings_version.',
37
+ });
38
+ if (!embeddings)
39
39
  return false;
40
- }
41
40
  const initSqlJs = (await mofloImport('sql.js'))?.default;
42
41
  if (!initSqlJs)
43
42
  return false;
@@ -68,6 +68,39 @@ export async function mofloImportRequired(specifier) {
68
68
  }
69
69
  return mod;
70
70
  }
71
+ /**
72
+ * Import a moflo-bundled package and loud-fail when it isn't resolvable.
73
+ *
74
+ * `mofloImport` returns null silently on resolution failure so probe-style
75
+ * callers (e.g. `mofloImport('sql.js')` for an optional dep) work cleanly.
76
+ * Packages bundled in the moflo tarball must be louder: an unresolved
77
+ * `@moflo/*` means a broken install, and silent skip leaves consumers stuck
78
+ * on stale state with no signal in their logs. Wrap with this helper at any
79
+ * call site where missing == broken.
80
+ *
81
+ * Behaviour:
82
+ * - Resolves: returns the module.
83
+ * - Unresolvable + `throwIfMissing: true`: throws Error with the same
84
+ * message that would otherwise be written to stderr (caller catches
85
+ * and surfaces a typed response — used by MCP handlers).
86
+ * - Unresolvable + `throwIfMissing: false` (default): writes one stderr
87
+ * line and returns null. Caller continues with a fallback path.
88
+ *
89
+ * The stderr line shape is `[<tag>] <specifier> not resolvable — <consequence>`,
90
+ * so log-grep and the consumer-smoke harness's stderr scan both pick it up.
91
+ */
92
+ export async function requireMofloOrWarn(specifier, expectedExports, opts) {
93
+ const mod = await mofloImport(specifier, expectedExports);
94
+ if (mod)
95
+ return mod;
96
+ const message = `[${opts.tag}] ${specifier} not resolvable — ${opts.consequence} ` +
97
+ `Indicates a broken moflo install (missing from tarball or hoisting failure).`;
98
+ if (opts.throwIfMissing) {
99
+ throw new Error(message);
100
+ }
101
+ process.stderr.write(message + '\n');
102
+ return null;
103
+ }
71
104
  /**
72
105
  * Resolve a package path without importing (useful for WASM file paths etc).
73
106
  * Returns the resolved path, or null if not found.
@@ -2,5 +2,5 @@
2
2
  * Auto-generated by build. Do not edit manually.
3
3
  * Source of truth: root package.json → scripts/sync-version.mjs
4
4
  */
5
- export const VERSION = '4.8.87-rc.2';
5
+ export const VERSION = '4.8.87-rc.3';
6
6
  //# sourceMappingURL=version.js.map
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@moflo/cli",
3
- "version": "4.8.87-rc.2",
3
+ "version": "4.8.87-rc.3",
4
4
  "type": "module",
5
5
  "main": "dist/src/index.js",
6
6
  "types": "dist/src/index.d.ts",