moflo 4.10.24 → 4.10.25
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/.claude/guidance/shipped/moflo-yaml-reference.md +5 -5
- package/.claude/skills/meditate/SKILL.md +2 -2
- package/bin/cli-hooks/statusline.js +12 -8
- package/bin/cli.js +1 -1
- package/bin/hooks.mjs +1 -1
- package/bin/lib/meditate.mjs +1 -0
- package/bin/lib/pii-scrub.mjs +2 -5
- package/dist/src/cli/commands/daemon.js +4 -3
- package/dist/src/cli/commands/doctor-checks-deep.js +2 -2
- package/dist/src/cli/commands/doctor-checks-swarm.js +122 -13
- package/dist/src/cli/commands/hooks.js +7 -23
- package/dist/src/cli/commands/init.js +1 -1
- package/dist/src/cli/commands/mcp.js +2 -1
- package/dist/src/cli/commands/session.js +1 -1
- package/dist/src/cli/commands/start.js +1 -1
- package/dist/src/cli/commands/status.js +1 -1
- package/dist/src/cli/commands/task.js +1 -1
- package/dist/src/cli/commands/update.js +12 -12
- package/dist/src/cli/guidance/analyzer.js +3 -3
- package/dist/src/cli/guidance/gates.js +1 -1
- package/dist/src/cli/guidance/hooks.js +1 -1
- package/dist/src/cli/guidance/meta-governance.js +1 -1
- package/dist/src/cli/hooks/index.js +1 -1
- package/dist/src/cli/hooks/reasoningbank/guidance-provider.js +1 -1
- package/dist/src/cli/hooks/workers/index.js +1 -1
- package/dist/src/cli/hooks/workers/session-hook.js +0 -40
- package/dist/src/cli/index.js +2 -2
- package/dist/src/cli/init/executor.js +36 -20
- package/dist/src/cli/init/mcp-generator.js +10 -8
- package/dist/src/cli/init/settings-generator.js +10 -7
- package/dist/src/cli/init/types.js +2 -2
- package/dist/src/cli/mcp-server.js +2 -1
- package/dist/src/cli/memory/bridge-loader.js +42 -0
- package/dist/src/cli/memory/embedding-model.js +157 -0
- package/dist/src/cli/memory/entries-read.js +380 -0
- package/dist/src/cli/memory/entries-shared.js +73 -0
- package/dist/src/cli/memory/entries-write.js +384 -0
- package/dist/src/cli/memory/hnsw-singleton.js +242 -0
- package/dist/src/cli/memory/init.js +367 -0
- package/dist/src/cli/memory/learnings-overview.js +156 -0
- package/dist/src/cli/memory/memory-initializer.js +37 -2257
- package/dist/src/cli/memory/quantization.js +221 -0
- package/dist/src/cli/memory/schema.js +382 -0
- package/dist/src/cli/memory/verify.js +178 -0
- package/dist/src/cli/movector/index.js +1 -1
- package/dist/src/cli/plugins/store/discovery.js +9 -9
- package/dist/src/cli/{transfer/ipfs/client.js → plugins/store/ipfs-client.js} +4 -1
- package/dist/src/cli/plugins/tests/demo-plugin-store.js +1 -1
- package/dist/src/cli/plugins/tests/standalone-test.js +1 -1
- package/dist/src/cli/runtime/headless.js +5 -4
- package/dist/src/cli/scripts/publish-registry.js +6 -6
- package/dist/src/cli/services/daemon-dashboard.js +108 -7
- package/dist/src/cli/services/daemon-readiness.js +1 -1
- package/dist/src/cli/services/daemon-service.js +1 -1
- package/dist/src/cli/services/env-compat.js +29 -0
- package/dist/src/cli/services/hook-block-hash.js +5 -6
- package/dist/src/cli/services/registry-api.js +1 -1
- package/dist/src/cli/shared/core/config/loader.js +19 -11
- package/dist/src/cli/shared/events/example-usage.js +2 -2
- package/dist/src/cli/shared/events/index.js +1 -1
- package/dist/src/cli/shared/index.js +1 -1
- package/dist/src/cli/shared/mcp/index.js +1 -1
- package/dist/src/cli/shared/mcp/server.js +3 -3
- package/dist/src/cli/shared/plugin-interface.js +1 -1
- package/dist/src/cli/shared/plugins/index.js +1 -1
- package/dist/src/cli/shared/plugins/official/index.js +1 -1
- package/dist/src/cli/shared/security/index.js +1 -1
- package/dist/src/cli/shared/services/v3-progress.service.js +40 -29
- package/dist/src/cli/shared/types.js +1 -1
- package/dist/src/cli/swarm/coordination/swarm-hub.js +1 -1
- package/dist/src/cli/update/index.js +1 -1
- package/dist/src/cli/update/rate-limiter.js +3 -2
- package/dist/src/cli/version.js +1 -1
- package/package.json +2 -2
- package/dist/src/cli/commands/transfer-store.js +0 -428
- package/dist/src/cli/transfer/anonymization/index.js +0 -281
- package/dist/src/cli/transfer/deploy-seraphine.js +0 -205
- package/dist/src/cli/transfer/export.js +0 -113
- package/dist/src/cli/transfer/index.js +0 -31
- package/dist/src/cli/transfer/ipfs/upload.js +0 -411
- package/dist/src/cli/transfer/models/seraphine.js +0 -373
- package/dist/src/cli/transfer/serialization/cfp.js +0 -184
- package/dist/src/cli/transfer/storage/gcs.js +0 -242
- package/dist/src/cli/transfer/storage/index.js +0 -6
- package/dist/src/cli/transfer/store/discovery.js +0 -382
- package/dist/src/cli/transfer/store/download.js +0 -334
- package/dist/src/cli/transfer/store/index.js +0 -153
- package/dist/src/cli/transfer/store/publish.js +0 -294
- package/dist/src/cli/transfer/store/registry.js +0 -285
- package/dist/src/cli/transfer/store/search.js +0 -232
- package/dist/src/cli/transfer/store/tests/standalone-test.js +0 -190
- package/dist/src/cli/transfer/store/types.js +0 -6
- package/dist/src/cli/transfer/test-seraphine.js +0 -105
- package/dist/src/cli/transfer/tests/test-store.js +0 -214
- package/dist/src/cli/transfer/types.js +0 -6
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* V3 Workers System - Cross-Platform Background Workers
|
|
3
3
|
*
|
|
4
|
-
* Optimizes
|
|
4
|
+
* Optimizes MoFlo with non-blocking, scheduled workers.
|
|
5
5
|
* Works on Linux, macOS, and Windows.
|
|
6
6
|
*/
|
|
7
7
|
import { EventEmitter } from 'events';
|
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
* Auto-starts workers when Claude Code session begins.
|
|
5
5
|
*/
|
|
6
6
|
import { createWorkerManager } from './index.js';
|
|
7
|
-
import * as path from 'path';
|
|
8
7
|
import { errorDetail } from '../../shared/utils/error-detail.js';
|
|
9
8
|
// ============================================================================
|
|
10
9
|
// Session Hook Functions
|
|
@@ -104,45 +103,6 @@ export function formatSessionStartOutput(result) {
|
|
|
104
103
|
return lines.join('\n');
|
|
105
104
|
}
|
|
106
105
|
// ============================================================================
|
|
107
|
-
// Shell Script Generator
|
|
108
|
-
// ============================================================================
|
|
109
|
-
/**
|
|
110
|
-
* Generate a shell hook script for integration with .claude/settings.json
|
|
111
|
-
*/
|
|
112
|
-
export function generateShellHook(projectRoot) {
|
|
113
|
-
const hookPath = path.join(projectRoot, 'v3', '@claude-flow', 'hooks');
|
|
114
|
-
return `#!/bin/bash
|
|
115
|
-
# Claude Flow V3 Workers - Session Start Hook
|
|
116
|
-
# Auto-generated - do not edit manually
|
|
117
|
-
|
|
118
|
-
set -euo pipefail
|
|
119
|
-
|
|
120
|
-
PROJECT_ROOT="${projectRoot}"
|
|
121
|
-
HOOKS_PATH="${hookPath}"
|
|
122
|
-
|
|
123
|
-
# Run worker initialization via Node.js
|
|
124
|
-
node --experimental-specifier-resolution=node -e "
|
|
125
|
-
const { onSessionStart, formatSessionStartOutput } = require('\${HOOKS_PATH}/dist/workers/session-hook.js');
|
|
126
|
-
|
|
127
|
-
async function main() {
|
|
128
|
-
const result = await onSessionStart({
|
|
129
|
-
projectRoot: '\${PROJECT_ROOT}',
|
|
130
|
-
autoStart: true,
|
|
131
|
-
runInitialScan: true,
|
|
132
|
-
workers: ['health', 'security', 'git'],
|
|
133
|
-
});
|
|
134
|
-
|
|
135
|
-
console.log(formatSessionStartOutput(result));
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
main().catch(err => {
|
|
139
|
-
console.error('[Workers] Error:', err.message);
|
|
140
|
-
process.exit(1);
|
|
141
|
-
});
|
|
142
|
-
"
|
|
143
|
-
`;
|
|
144
|
-
}
|
|
145
|
-
// ============================================================================
|
|
146
106
|
// Integration Helper
|
|
147
107
|
// ============================================================================
|
|
148
108
|
/**
|
package/dist/src/cli/index.js
CHANGED
|
@@ -490,14 +490,14 @@ export class CLI {
|
|
|
490
490
|
? spawn(`"${process.execPath}" ${spawnArgs.map(a => `"${a}"`).join(' ')}`, [], {
|
|
491
491
|
cwd: projectRoot,
|
|
492
492
|
stdio: ['ignore', openSync(logFile, 'a'), openSync(logFile, 'a')],
|
|
493
|
-
env: { ...process.env,
|
|
493
|
+
env: { ...process.env, MOFLO_DAEMON: '1' },
|
|
494
494
|
shell: true, windowsHide: true,
|
|
495
495
|
})
|
|
496
496
|
: spawn(process.execPath, spawnArgs, {
|
|
497
497
|
cwd: projectRoot,
|
|
498
498
|
detached: true,
|
|
499
499
|
stdio: ['ignore', openSync(logFile, 'a'), openSync(logFile, 'a')],
|
|
500
|
-
env: { ...process.env,
|
|
500
|
+
env: { ...process.env, MOFLO_DAEMON: '1' },
|
|
501
501
|
});
|
|
502
502
|
child.unref();
|
|
503
503
|
// Register the spawned daemon PID with the shared ProcessManager so that
|
|
@@ -21,6 +21,7 @@ import { writeEnvrc } from './envrc-generator.js';
|
|
|
21
21
|
import { repairHookWiring } from '../services/hook-wiring.js';
|
|
22
22
|
import { locateMofloRootPath } from '../services/moflo-require.js';
|
|
23
23
|
import { errorDetail } from '../shared/utils/error-detail.js';
|
|
24
|
+
import { readMofloEnv } from '../services/env-compat.js';
|
|
24
25
|
/**
|
|
25
26
|
* Skills to copy based on configuration. Exported for integrity tests.
|
|
26
27
|
*/
|
|
@@ -206,15 +207,19 @@ function mergeSettingsForUpgrade(existing) {
|
|
|
206
207
|
// Mac/Linux: Use bash-compatible commands with 2>/dev/null
|
|
207
208
|
// NOTE: teammateIdleCmd and taskCompletedCmd were removed.
|
|
208
209
|
// TeammateIdle/TaskCompleted are not valid Claude Code hook events and caused warnings.
|
|
209
|
-
// Agent Teams hook config lives in
|
|
210
|
+
// Agent Teams hook config lives in moflo.agentTeams.hooks instead.
|
|
210
211
|
// 1. Merge env vars (preserve existing, add new)
|
|
211
212
|
const existingEnv = existing.env || {};
|
|
212
213
|
const newEnv = {
|
|
213
214
|
...existingEnv,
|
|
214
215
|
CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS: '1',
|
|
215
|
-
|
|
216
|
-
|
|
216
|
+
// #1209 — emit MOFLO_* names; carry any pre-rebrand value forward, then
|
|
217
|
+
// drop the legacy keys so a consumer's settings.json ends up clean.
|
|
218
|
+
MOFLO_V3_ENABLED: existingEnv.MOFLO_V3_ENABLED || existingEnv.CLAUDE_FLOW_V3_ENABLED || 'true',
|
|
219
|
+
MOFLO_HOOKS_ENABLED: existingEnv.MOFLO_HOOKS_ENABLED || existingEnv.CLAUDE_FLOW_HOOKS_ENABLED || 'true',
|
|
217
220
|
};
|
|
221
|
+
delete newEnv.CLAUDE_FLOW_V3_ENABLED;
|
|
222
|
+
delete newEnv.CLAUDE_FLOW_HOOKS_ENABLED;
|
|
218
223
|
// Remove stale PATH override — ${PATH} isn't expanded by Claude Code,
|
|
219
224
|
// which replaces the inherited PATH and breaks node resolution in hooks.
|
|
220
225
|
delete newEnv.PATH;
|
|
@@ -269,7 +274,7 @@ function mergeSettingsForUpgrade(existing) {
|
|
|
269
274
|
// Remove them if they exist from a previous init.
|
|
270
275
|
delete merged.hooks.TeammateIdle;
|
|
271
276
|
delete merged.hooks.TaskCompleted;
|
|
272
|
-
// Their configuration lives in
|
|
277
|
+
// Their configuration lives in moflo.agentTeams.hooks instead.
|
|
273
278
|
// 3. Fix statusLine config (remove invalid fields, ensure correct format)
|
|
274
279
|
// Claude Code only supports: type, command, padding
|
|
275
280
|
// Always ensure statusLine is present — add it if missing (e.g. from older inits)
|
|
@@ -279,13 +284,19 @@ function mergeSettingsForUpgrade(existing) {
|
|
|
279
284
|
command: existingStatusLine?.command || `node "$CLAUDE_PROJECT_DIR/.claude/helpers/statusline.cjs"`,
|
|
280
285
|
// Remove invalid fields: refreshMs, enabled (not supported by Claude Code)
|
|
281
286
|
};
|
|
282
|
-
// 4. Merge
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
287
|
+
// 4. Merge moflo settings (preserve existing, add agentTeams + memory).
|
|
288
|
+
// #1209 — read the canonical `moflo.*` tree, falling back to the pre-rebrand
|
|
289
|
+
// `claudeFlow.*` tree, write `moflo.*`, then drop the legacy tree so the
|
|
290
|
+
// consumer's settings.json migrates in place. The `hooks.locked` escape
|
|
291
|
+
// hatch survives the move via the spread.
|
|
292
|
+
const existingMofloTree = existing.moflo ||
|
|
293
|
+
existing.claudeFlow ||
|
|
294
|
+
{};
|
|
295
|
+
const existingMemory = existingMofloTree.memory || {};
|
|
296
|
+
merged.moflo = {
|
|
297
|
+
...existingMofloTree,
|
|
298
|
+
version: existingMofloTree.version || '3.0.0',
|
|
299
|
+
enabled: existingMofloTree.enabled !== false,
|
|
289
300
|
agentTeams: {
|
|
290
301
|
enabled: true,
|
|
291
302
|
teammateMode: 'auto',
|
|
@@ -309,6 +320,8 @@ function mergeSettingsForUpgrade(existing) {
|
|
|
309
320
|
agentScopes: existingMemory.agentScopes ?? { enabled: true },
|
|
310
321
|
},
|
|
311
322
|
};
|
|
323
|
+
// Drop the pre-rebrand tree now that its content lives under `moflo.*`.
|
|
324
|
+
delete merged.claudeFlow;
|
|
312
325
|
// 5. Repair any missing required hook wirings (same logic doctor --fix uses)
|
|
313
326
|
repairHookWiring(merged);
|
|
314
327
|
return merged;
|
|
@@ -579,15 +592,18 @@ export async function executeUpgrade(targetDir, _upgradeSettings = false) {
|
|
|
579
592
|
else {
|
|
580
593
|
result.preserved.push('.moflo/security/audit-status.json');
|
|
581
594
|
}
|
|
582
|
-
// 3. Fix .mcp.json —
|
|
595
|
+
// 3. Fix .mcp.json — migrate any legacy CLI package spec to moflo.
|
|
596
|
+
// Consumers may carry an older scoped CLI package — the pre-#586 `claude-flow/cli`
|
|
597
|
+
// or the transient post-#586 `@moflo/cli`; both collapse to the `moflo` package.
|
|
598
|
+
// (Prior code checked one scope but replaced the other, so it never fired.)
|
|
583
599
|
const mcpPath = path.join(targetDir, '.mcp.json');
|
|
584
600
|
if (fs.existsSync(mcpPath)) {
|
|
585
601
|
try {
|
|
586
602
|
const mcpRaw = fs.readFileSync(mcpPath, 'utf-8');
|
|
587
|
-
|
|
588
|
-
|
|
603
|
+
const mcpFixed = mcpRaw.replace(/@(?:claude-flow|moflo)\/cli(@latest)?/g, 'moflo');
|
|
604
|
+
if (mcpFixed !== mcpRaw) {
|
|
589
605
|
fs.writeFileSync(mcpPath, mcpFixed, 'utf-8');
|
|
590
|
-
result.updated.push('.mcp.json (
|
|
606
|
+
result.updated.push('.mcp.json (migrated legacy CLI package spec to moflo)');
|
|
591
607
|
}
|
|
592
608
|
}
|
|
593
609
|
catch {
|
|
@@ -612,8 +628,8 @@ export async function executeUpgrade(targetDir, _upgradeSettings = false) {
|
|
|
612
628
|
'hooks.TeammateIdle (removed — not a valid Claude Code hook)',
|
|
613
629
|
'hooks.TaskCompleted (removed — not a valid Claude Code hook)',
|
|
614
630
|
'hooks (repaired missing gate wirings)',
|
|
615
|
-
'
|
|
616
|
-
'
|
|
631
|
+
'moflo.agentTeams',
|
|
632
|
+
'moflo.memory (learningBridge, memoryGraph, agentScopes)',
|
|
617
633
|
'statusLine',
|
|
618
634
|
];
|
|
619
635
|
}
|
|
@@ -721,7 +737,7 @@ export async function executeUpgradeWithMissing(targetDir, _upgradeSettings = fa
|
|
|
721
737
|
const sourceAgentsDir = findSourceDir('agents');
|
|
722
738
|
const sourceCommandsDir = findSourceDir('commands');
|
|
723
739
|
// Debug: Log source directories found
|
|
724
|
-
if (process.env.DEBUG ||
|
|
740
|
+
if (process.env.DEBUG || readMofloEnv('DEBUG')) {
|
|
725
741
|
console.log('[DEBUG] Source directories:');
|
|
726
742
|
console.log(` Skills: ${sourceSkillsDir || 'NOT FOUND'}`);
|
|
727
743
|
console.log(` Agents: ${sourceAgentsDir || 'NOT FOUND'}`);
|
|
@@ -730,7 +746,7 @@ export async function executeUpgradeWithMissing(targetDir, _upgradeSettings = fa
|
|
|
730
746
|
// Add missing skills
|
|
731
747
|
if (sourceSkillsDir) {
|
|
732
748
|
const allSkills = Object.values(SKILLS_MAP).flat();
|
|
733
|
-
const debugMode = process.env.DEBUG ||
|
|
749
|
+
const debugMode = process.env.DEBUG || readMofloEnv('DEBUG');
|
|
734
750
|
if (debugMode) {
|
|
735
751
|
console.log(`[DEBUG] Checking ${allSkills.length} skills from SKILLS_MAP`);
|
|
736
752
|
}
|
|
@@ -1419,7 +1435,7 @@ async function writeInitialMetrics(targetDir, options, result) {
|
|
|
1419
1435
|
}
|
|
1420
1436
|
}
|
|
1421
1437
|
/**
|
|
1422
|
-
* Write CAPABILITIES.md - comprehensive overview of all
|
|
1438
|
+
* Write CAPABILITIES.md - comprehensive overview of all MoFlo features
|
|
1423
1439
|
*/
|
|
1424
1440
|
async function writeCapabilitiesDoc(targetDir, options, result) {
|
|
1425
1441
|
const capabilitiesPath = path.join(targetDir, '.moflo', 'CAPABILITIES.md');
|
|
@@ -57,16 +57,18 @@ export function generateMCPConfig(options) {
|
|
|
57
57
|
// When toolDefer is true, emit "deferred" so Claude Code loads schemas on
|
|
58
58
|
// demand via ToolSearch instead of putting 150+ schemas into context at startup.
|
|
59
59
|
const deferProps = config.toolDefer ? { toolDefer: 'deferred' } : {};
|
|
60
|
+
// #1209 — write MOFLO_* into the consumer's .mcp.json; the runtime readers
|
|
61
|
+
// (loader.ts etc.) still accept the pre-rebrand CLAUDE_FLOW_* names.
|
|
60
62
|
const mcpEnv = {
|
|
61
63
|
...npmEnv,
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
64
|
+
MOFLO_MODE: 'v3',
|
|
65
|
+
MOFLO_HOOKS_ENABLED: 'true',
|
|
66
|
+
MOFLO_TOPOLOGY: options.runtime.topology,
|
|
67
|
+
MOFLO_MAX_AGENTS: String(options.runtime.maxAgents),
|
|
68
|
+
MOFLO_MEMORY_BACKEND: options.runtime.memoryBackend,
|
|
67
69
|
};
|
|
68
|
-
//
|
|
69
|
-
if (config.
|
|
70
|
+
// moflo MCP server (core) — use direct node when locally installed
|
|
71
|
+
if (config.moflo) {
|
|
70
72
|
const projectRoot = options.targetDir ?? process.cwd();
|
|
71
73
|
const localCli = findMofloCli(projectRoot);
|
|
72
74
|
if (localCli) {
|
|
@@ -100,7 +102,7 @@ export function generateMCPCommands(options) {
|
|
|
100
102
|
const commands = [];
|
|
101
103
|
const config = options.mcp;
|
|
102
104
|
const cmdPrefix = isWindows ? 'cmd /c ' : '';
|
|
103
|
-
if (config.
|
|
105
|
+
if (config.moflo) {
|
|
104
106
|
const projectRoot = options.targetDir ?? process.cwd();
|
|
105
107
|
const localCli = findMofloCli(projectRoot);
|
|
106
108
|
if (localCli) {
|
|
@@ -39,20 +39,23 @@ export function generateSettings(options) {
|
|
|
39
39
|
pr: '🤖 Generated with [moflo](https://github.com/eric-cielo/moflo)',
|
|
40
40
|
};
|
|
41
41
|
// Note: Claude Code expects 'model' to be a string, not an object
|
|
42
|
-
// Model preferences are stored in
|
|
42
|
+
// Model preferences are stored in moflo settings instead
|
|
43
43
|
// settings.model = 'claude-sonnet-4-5-20250929'; // Uncomment if you want to set a default model
|
|
44
44
|
// Add Agent Teams configuration (experimental feature)
|
|
45
45
|
settings.env = {
|
|
46
46
|
// Enable Claude Code Agent Teams for multi-agent coordination
|
|
47
47
|
CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS: '1',
|
|
48
|
-
//
|
|
49
|
-
|
|
50
|
-
|
|
48
|
+
// moflo-specific environment (#1209 — emit MOFLO_*; readers still accept
|
|
49
|
+
// the pre-rebrand CLAUDE_FLOW_* names as a fallback via env-compat.ts)
|
|
50
|
+
MOFLO_V3_ENABLED: 'true',
|
|
51
|
+
MOFLO_HOOKS_ENABLED: 'true',
|
|
51
52
|
};
|
|
52
53
|
// Detect platform for platform-aware configuration
|
|
53
54
|
const platform = detectPlatform();
|
|
54
|
-
// Add V3-specific settings
|
|
55
|
-
|
|
55
|
+
// Add V3-specific settings (#1209 — canonical `moflo.*` tree; the pre-rebrand
|
|
56
|
+
// `claudeFlow.*` tree is still read as a fallback by hook-block-hash + the
|
|
57
|
+
// upgrade merge for consumers who haven't re-run init yet)
|
|
58
|
+
settings.moflo = {
|
|
56
59
|
version: '3.0.0',
|
|
57
60
|
enabled: true,
|
|
58
61
|
platform: {
|
|
@@ -434,7 +437,7 @@ function generateHooksConfig(config) {
|
|
|
434
437
|
];
|
|
435
438
|
}
|
|
436
439
|
// NOTE: TeammateIdle and TaskCompleted are NOT valid Claude Code hook events.
|
|
437
|
-
// Their configuration lives in
|
|
440
|
+
// Their configuration lives in moflo.agentTeams.hooks instead (see generateSettings).
|
|
438
441
|
return hooks;
|
|
439
442
|
}
|
|
440
443
|
/**
|
|
@@ -109,7 +109,7 @@ export const DEFAULT_INIT_OPTIONS = {
|
|
|
109
109
|
refreshInterval: 5000,
|
|
110
110
|
},
|
|
111
111
|
mcp: {
|
|
112
|
-
|
|
112
|
+
moflo: true,
|
|
113
113
|
ruvSwarm: false,
|
|
114
114
|
flowNexus: false,
|
|
115
115
|
autoStart: false,
|
|
@@ -230,7 +230,7 @@ export const FULL_INIT_OPTIONS = {
|
|
|
230
230
|
all: true,
|
|
231
231
|
},
|
|
232
232
|
mcp: {
|
|
233
|
-
|
|
233
|
+
moflo: true,
|
|
234
234
|
ruvSwarm: true,
|
|
235
235
|
flowNexus: true,
|
|
236
236
|
autoStart: false,
|
|
@@ -25,6 +25,7 @@ import { fileURLToPath } from 'url';
|
|
|
25
25
|
import { dirname } from 'path';
|
|
26
26
|
import { errorDetail } from './shared/utils/error-detail.js';
|
|
27
27
|
import { findProjectRoot } from './services/project-root.js';
|
|
28
|
+
import { readMofloEnv } from './services/env-compat.js';
|
|
28
29
|
// ESM-compatible __dirname
|
|
29
30
|
const __filename = fileURLToPath(import.meta.url);
|
|
30
31
|
const __dirname = dirname(__filename);
|
|
@@ -205,7 +206,7 @@ export class MCPServerManager extends EventEmitter {
|
|
|
205
206
|
// No PID file found. Detect if we are running in stdio mode
|
|
206
207
|
// (e.g., launched by Claude Code via `claude mcp add`).
|
|
207
208
|
const isStdio = !process.stdin.isTTY;
|
|
208
|
-
const envTransport =
|
|
209
|
+
const envTransport = readMofloEnv('MCP_TRANSPORT');
|
|
209
210
|
if (isStdio || envTransport === 'stdio' || this.options.transport === 'stdio') {
|
|
210
211
|
return {
|
|
211
212
|
running: true,
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lazy AgentDB v3 bridge loader (ADR-053).
|
|
3
|
+
*
|
|
4
|
+
* Extracted from `memory-initializer.ts` (#1203 decomposition) so the
|
|
5
|
+
* HNSW, embedding, entry-CRUD, and init modules share ONE process-wide
|
|
6
|
+
* bridge singleton instead of each holding their own. Behaviour is
|
|
7
|
+
* identical to the pre-split inline `getBridge()`: first call attempts the
|
|
8
|
+
* dynamic import; a failure caches `null` so subsequent calls short-circuit.
|
|
9
|
+
*
|
|
10
|
+
* @module memory/bridge-loader
|
|
11
|
+
*/
|
|
12
|
+
// ADR-053: Lazy import of AgentDB v3 bridge.
|
|
13
|
+
// `undefined` = not yet attempted; `null` = attempted and failed (cached).
|
|
14
|
+
let _bridge;
|
|
15
|
+
/**
|
|
16
|
+
* Return the lazily-loaded memory-bridge module, or `null` if it (or its
|
|
17
|
+
* native deps) can't be loaded. Result is memoized — a failed load caches
|
|
18
|
+
* `null` so we don't retry the import on every call.
|
|
19
|
+
*/
|
|
20
|
+
export async function getBridge() {
|
|
21
|
+
if (_bridge === null)
|
|
22
|
+
return null;
|
|
23
|
+
if (_bridge)
|
|
24
|
+
return _bridge;
|
|
25
|
+
try {
|
|
26
|
+
_bridge = await import('./memory-bridge.js');
|
|
27
|
+
return _bridge;
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
_bridge = null;
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* True once the bridge module has been successfully loaded. Lets callers
|
|
36
|
+
* (e.g. `getHNSWStatus`) report AgentDB-v3 availability without forcing a
|
|
37
|
+
* load. Mirrors the pre-split `_bridge && _bridge !== null` check.
|
|
38
|
+
*/
|
|
39
|
+
export function isBridgeLoaded() {
|
|
40
|
+
return !!_bridge;
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=bridge-loader.js.map
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Neural embedding model manager.
|
|
3
|
+
*
|
|
4
|
+
* Extracted from `memory-initializer.ts` (#1203 decomposition). Lazily loads
|
|
5
|
+
* the fastembed-backed embedding service (ONNX all-MiniLM-L6-v2) and generates
|
|
6
|
+
* embeddings. There is NO hash fallback — a failed model load throws (hash
|
|
7
|
+
* embeddings were removed in epic #527).
|
|
8
|
+
*
|
|
9
|
+
* @module memory/embedding-model
|
|
10
|
+
*/
|
|
11
|
+
import { formatEmbeddingError } from './embedding-errors.js';
|
|
12
|
+
import { getBridge } from './bridge-loader.js';
|
|
13
|
+
let embeddingModelState = null;
|
|
14
|
+
/**
|
|
15
|
+
* Lazy-load the neural embedding service.
|
|
16
|
+
*
|
|
17
|
+
* Delegates to the local fastembed-backed service. Returns a diagnostic
|
|
18
|
+
* result for callers that want to report status; if model loading fails later
|
|
19
|
+
* on first `embed()`, that throws from `generateEmbedding`.
|
|
20
|
+
*/
|
|
21
|
+
export async function loadEmbeddingModel(options) {
|
|
22
|
+
const { verbose = false } = options || {};
|
|
23
|
+
const startTime = Date.now();
|
|
24
|
+
if (embeddingModelState?.loaded) {
|
|
25
|
+
return {
|
|
26
|
+
success: true,
|
|
27
|
+
dimensions: embeddingModelState.dimensions,
|
|
28
|
+
modelName: 'cached',
|
|
29
|
+
loadTime: 0,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
// ADR-053: Try AgentDB v3 bridge first
|
|
33
|
+
const bridge = await getBridge();
|
|
34
|
+
if (bridge) {
|
|
35
|
+
const bridgeResult = await bridge.bridgeLoadEmbeddingModel();
|
|
36
|
+
if (bridgeResult && bridgeResult.success) {
|
|
37
|
+
embeddingModelState = {
|
|
38
|
+
loaded: true,
|
|
39
|
+
service: null, // Bridge handles embedding
|
|
40
|
+
dimensions: bridgeResult.dimensions,
|
|
41
|
+
modelName: bridgeResult.modelName || 'bridge',
|
|
42
|
+
};
|
|
43
|
+
return bridgeResult;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
if (verbose) {
|
|
47
|
+
console.log('Preparing neural embedding runtime (fastembed / all-MiniLM-L6-v2)...');
|
|
48
|
+
}
|
|
49
|
+
const { createEmbeddingService } = await import('../embeddings/embedding-service.js');
|
|
50
|
+
const service = createEmbeddingService({
|
|
51
|
+
provider: 'fastembed',
|
|
52
|
+
dimensions: 384,
|
|
53
|
+
});
|
|
54
|
+
embeddingModelState = {
|
|
55
|
+
loaded: true,
|
|
56
|
+
service,
|
|
57
|
+
dimensions: 384,
|
|
58
|
+
modelName: 'fastembed/all-MiniLM-L6-v2',
|
|
59
|
+
};
|
|
60
|
+
return {
|
|
61
|
+
success: true,
|
|
62
|
+
dimensions: 384,
|
|
63
|
+
modelName: 'fastembed/all-MiniLM-L6-v2',
|
|
64
|
+
loadTime: Date.now() - startTime,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Generate a neural embedding for text.
|
|
69
|
+
*
|
|
70
|
+
* Uses the fastembed-backed service from cli's embeddings module. Throws on model
|
|
71
|
+
* load / inference failure — there is no hash fallback.
|
|
72
|
+
*/
|
|
73
|
+
export async function generateEmbedding(text) {
|
|
74
|
+
// ADR-053: Try AgentDB v3 bridge first
|
|
75
|
+
const bridge = await getBridge();
|
|
76
|
+
if (bridge) {
|
|
77
|
+
const bridgeResult = await bridge.bridgeGenerateEmbedding(text);
|
|
78
|
+
if (bridgeResult)
|
|
79
|
+
return bridgeResult;
|
|
80
|
+
}
|
|
81
|
+
if (!embeddingModelState?.loaded) {
|
|
82
|
+
const load = await loadEmbeddingModel();
|
|
83
|
+
if (!load.success) {
|
|
84
|
+
throw new Error(formatEmbeddingError(load.error ?? 'unknown error'));
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
const state = embeddingModelState;
|
|
88
|
+
if (!state.service) {
|
|
89
|
+
throw new Error(`Embedding model state has no active service. Bridge-backed state requires ` +
|
|
90
|
+
`bridge.bridgeGenerateEmbedding(); hash fallback was removed in epic #527.`);
|
|
91
|
+
}
|
|
92
|
+
let result;
|
|
93
|
+
try {
|
|
94
|
+
result = await state.service.embed(text);
|
|
95
|
+
}
|
|
96
|
+
catch (err) {
|
|
97
|
+
throw new Error(formatEmbeddingError(err));
|
|
98
|
+
}
|
|
99
|
+
const embedding = Array.from(result.embedding);
|
|
100
|
+
return {
|
|
101
|
+
embedding,
|
|
102
|
+
dimensions: embedding.length,
|
|
103
|
+
model: state.modelName,
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Generate embeddings for multiple texts
|
|
108
|
+
* Uses parallel execution for API-based providers (2-4x faster)
|
|
109
|
+
* Note: Local ONNX inference is CPU-bound, so parallelism has limited benefit
|
|
110
|
+
*
|
|
111
|
+
* @param texts - Array of texts to embed
|
|
112
|
+
* @param options - Batch options
|
|
113
|
+
* @returns Array of embedding results with timing info
|
|
114
|
+
*/
|
|
115
|
+
export async function generateBatchEmbeddings(texts, options) {
|
|
116
|
+
const { concurrency = texts.length, onProgress } = options || {};
|
|
117
|
+
const startTime = Date.now();
|
|
118
|
+
// Ensure model is loaded first (prevents cold start in parallel)
|
|
119
|
+
if (!embeddingModelState?.loaded) {
|
|
120
|
+
await loadEmbeddingModel();
|
|
121
|
+
}
|
|
122
|
+
// Process in parallel with optional concurrency limit
|
|
123
|
+
if (concurrency >= texts.length) {
|
|
124
|
+
// Full parallelism
|
|
125
|
+
const embeddings = await Promise.all(texts.map(async (text, i) => {
|
|
126
|
+
const result = await generateEmbedding(text);
|
|
127
|
+
onProgress?.(i + 1, texts.length);
|
|
128
|
+
return { text, ...result };
|
|
129
|
+
}));
|
|
130
|
+
const totalTime = Date.now() - startTime;
|
|
131
|
+
return {
|
|
132
|
+
results: embeddings,
|
|
133
|
+
totalTime,
|
|
134
|
+
avgTime: totalTime / texts.length
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
// Limited concurrency using chunking
|
|
138
|
+
const results = [];
|
|
139
|
+
let completed = 0;
|
|
140
|
+
for (let i = 0; i < texts.length; i += concurrency) {
|
|
141
|
+
const chunk = texts.slice(i, i + concurrency);
|
|
142
|
+
const chunkResults = await Promise.all(chunk.map(async (text) => {
|
|
143
|
+
const result = await generateEmbedding(text);
|
|
144
|
+
completed++;
|
|
145
|
+
onProgress?.(completed, texts.length);
|
|
146
|
+
return { text, ...result };
|
|
147
|
+
}));
|
|
148
|
+
results.push(...chunkResults);
|
|
149
|
+
}
|
|
150
|
+
const totalTime = Date.now() - startTime;
|
|
151
|
+
return {
|
|
152
|
+
results,
|
|
153
|
+
totalTime,
|
|
154
|
+
avgTime: totalTime / texts.length
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
//# sourceMappingURL=embedding-model.js.map
|