cf-doctor 1.0.0
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/LICENSE +21 -0
- package/README.md +161 -0
- package/bin/cf-doctor.js +18 -0
- package/dist/doctor.d.ts +21 -0
- package/dist/doctor.d.ts.map +1 -0
- package/dist/doctor.js +33 -0
- package/dist/doctor.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp-server.d.ts +12 -0
- package/dist/mcp-server.d.ts.map +1 -0
- package/dist/mcp-server.js +200 -0
- package/dist/mcp-server.js.map +1 -0
- package/dist/patches/apply.d.ts +7 -0
- package/dist/patches/apply.d.ts.map +1 -0
- package/dist/patches/apply.js +51 -0
- package/dist/patches/apply.js.map +1 -0
- package/dist/persistence/episodes.d.ts +42 -0
- package/dist/persistence/episodes.d.ts.map +1 -0
- package/dist/persistence/episodes.js +160 -0
- package/dist/persistence/episodes.js.map +1 -0
- package/dist/persistence/index.d.ts +4 -0
- package/dist/persistence/index.d.ts.map +1 -0
- package/dist/persistence/index.js +4 -0
- package/dist/persistence/index.js.map +1 -0
- package/dist/persistence/q-table.d.ts +42 -0
- package/dist/persistence/q-table.d.ts.map +1 -0
- package/dist/persistence/q-table.js +138 -0
- package/dist/persistence/q-table.js.map +1 -0
- package/dist/persistence/sona.d.ts +45 -0
- package/dist/persistence/sona.d.ts.map +1 -0
- package/dist/persistence/sona.js +142 -0
- package/dist/persistence/sona.js.map +1 -0
- package/package.json +63 -0
- package/patches/README.md +68 -0
- package/patches/neural-index.patch +8 -0
- package/patches/quick-test.patch +25 -0
- package/patches/sona-integration.patch +76 -0
- package/patches/version-bridge.patch +30 -0
- package/scripts/cf-doctor.sh +684 -0
- package/tests/run-all-tests.sh +32 -0
- package/tests/test-01-doctor-passes.sh +43 -0
- package/tests/test-02-mcp-init.sh +36 -0
- package/tests/test-03-agent-spawn-no-ruvector.sh +84 -0
- package/tests/test-04-agent-spawn-with-ruvector.sh +37 -0
- package/tests/test-05-learning-persists.sh +94 -0
- package/tests/test-06-hooks-version-bridge.sh +82 -0
- package/tests/test-helpers.sh +88 -0
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# @ruvector/* Import Fix Patches
|
|
2
|
+
|
|
3
|
+
These patches fix crashes that occur when `@ruvector/*` WASM packages are not
|
|
4
|
+
installed. Each patch converts a hard static import into a dynamic import with
|
|
5
|
+
an in-memory fallback, so claude-flow runs correctly without the optional native
|
|
6
|
+
backends.
|
|
7
|
+
|
|
8
|
+
## Patches
|
|
9
|
+
|
|
10
|
+
| File | Target Repo | Severity | Description |
|
|
11
|
+
|------|------------|----------|-------------|
|
|
12
|
+
| `sona-integration.patch` | claude-flow | CRITICAL | Replaces static `@ruvector/sona` import with lazy dynamic import + MockSonaEngine fallback |
|
|
13
|
+
| `neural-index.patch` | claude-flow | CRITICAL | Updates barrel file comments; safe once sona-integration is patched |
|
|
14
|
+
| `quick-test.patch` | claude-flow | LOW | Replaces static `@ruvector/attention` import in benchmark example |
|
|
15
|
+
| `version-bridge.patch` | ruvector | NORMAL | Detects claude-flow v2 vs v3 CLI syntax before spawning hooks |
|
|
16
|
+
|
|
17
|
+
## Apply Instructions
|
|
18
|
+
|
|
19
|
+
### claude-flow repo (Patches A, B, C)
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
cd claude-flow
|
|
23
|
+
git apply /tmp/cf-integration-fixes/patches/sona-integration.patch
|
|
24
|
+
git apply /tmp/cf-integration-fixes/patches/neural-index.patch
|
|
25
|
+
git apply /tmp/cf-integration-fixes/patches/quick-test.patch
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### ruvector repo (Patch D)
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
cd ruvector
|
|
32
|
+
git apply /tmp/cf-integration-fixes/patches/version-bridge.patch
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### Dry-run (check without applying)
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
git apply --check /tmp/cf-integration-fixes/patches/sona-integration.patch
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### Reverse a patch
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
git apply -R /tmp/cf-integration-fixes/patches/sona-integration.patch
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Verification
|
|
48
|
+
|
|
49
|
+
After applying, confirm no static `@ruvector/*` imports remain in critical paths:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
# Should return zero results for patched files
|
|
53
|
+
grep -rn "from '@ruvector/" v3/@claude-flow/neural/src/sona-integration.ts
|
|
54
|
+
grep -rn "from '@ruvector/" v3/@claude-flow/performance/src/examples/quick-test.ts
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Test that the mock fallback activates cleanly (without @ruvector installed):
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
npx tsx -e "
|
|
61
|
+
import { SonaIntegration } from './v3/@claude-flow/neural/index';
|
|
62
|
+
const s = new SonaIntegration();
|
|
63
|
+
s.storePattern('test', { v: 1 }).then(() => {
|
|
64
|
+
console.log('mock:', s.isUsingMock());
|
|
65
|
+
return s.recallPattern('test');
|
|
66
|
+
}).then(r => console.log('recalled:', r));
|
|
67
|
+
"
|
|
68
|
+
```
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
--- a/v3/@claude-flow/neural/index.ts
|
|
2
|
+
+++ b/v3/@claude-flow/neural/index.ts
|
|
3
|
+
@@ -1,3 +1,4 @@
|
|
4
|
+
export { SonaIntegration } from './src/sona-integration';
|
|
5
|
+
export { NeuralRouter } from './src/neural-router';
|
|
6
|
+
-// ... other exports that depend on @ruvector
|
|
7
|
+
+// Re-exports are safe now because sona-integration uses dynamic import internally
|
|
8
|
+
+// No @ruvector/* static imports leak through this barrel file
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
--- a/v3/@claude-flow/performance/src/examples/quick-test.ts
|
|
2
|
+
+++ b/v3/@claude-flow/performance/src/examples/quick-test.ts
|
|
3
|
+
@@ -1,7 +1,19 @@
|
|
4
|
+
-import { FlashAttention } from '@ruvector/attention';
|
|
5
|
+
-
|
|
6
|
+
async function runBenchmark() {
|
|
7
|
+
- const attn = new FlashAttention({ headDim: 64 });
|
|
8
|
+
+ let FlashAttention: any;
|
|
9
|
+
+ try {
|
|
10
|
+
+ const mod = await import('@ruvector/attention');
|
|
11
|
+
+ FlashAttention = mod.FlashAttention;
|
|
12
|
+
+ } catch {
|
|
13
|
+
+ console.warn('[perf] @ruvector/attention not available, using mock');
|
|
14
|
+
+ FlashAttention = class MockFlashAttention {
|
|
15
|
+
+ constructor(private opts: any) {}
|
|
16
|
+
+ async forward(q: any, k: any, v: any) {
|
|
17
|
+
+ // Mock: return zero tensor of expected shape
|
|
18
|
+
+ return { output: new Float32Array(this.opts.headDim || 64), mockResult: true };
|
|
19
|
+
+ }
|
|
20
|
+
+ };
|
|
21
|
+
+ }
|
|
22
|
+
+
|
|
23
|
+
+ const attn = new FlashAttention({ headDim: 64 });
|
|
24
|
+
// ...rest of benchmark
|
|
25
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
--- a/v3/@claude-flow/neural/src/sona-integration.ts
|
|
2
|
+
+++ b/v3/@claude-flow/neural/src/sona-integration.ts
|
|
3
|
+
@@ -1,27 +1,55 @@
|
|
4
|
+
-import { SonaEngine } from '@ruvector/sona';
|
|
5
|
+
+// Dynamic import with fallback - @ruvector/sona is optional
|
|
6
|
+
+let SonaEngineImpl: any = null;
|
|
7
|
+
|
|
8
|
+
-export class SonaIntegration {
|
|
9
|
+
- private engine: SonaEngine;
|
|
10
|
+
+async function loadSonaEngine(): Promise<any> {
|
|
11
|
+
+ if (SonaEngineImpl !== null) return SonaEngineImpl;
|
|
12
|
+
+ try {
|
|
13
|
+
+ const mod = await import('@ruvector/sona');
|
|
14
|
+
+ SonaEngineImpl = mod.SonaEngine;
|
|
15
|
+
+ return SonaEngineImpl;
|
|
16
|
+
+ } catch {
|
|
17
|
+
+ // @ruvector/sona not installed - use in-memory mock
|
|
18
|
+
+ SonaEngineImpl = class MockSonaEngine {
|
|
19
|
+
+ private store = new Map<string, any>();
|
|
20
|
+
|
|
21
|
+
- constructor() {
|
|
22
|
+
- this.engine = new SonaEngine();
|
|
23
|
+
- }
|
|
24
|
+
+ async store(key: string, pattern: any): Promise<void> {
|
|
25
|
+
+ this.store.set(key, pattern);
|
|
26
|
+
+ }
|
|
27
|
+
|
|
28
|
+
- async storePattern(key: string, pattern: any): Promise<void> {
|
|
29
|
+
- await this.engine.store(key, pattern);
|
|
30
|
+
- }
|
|
31
|
+
+ async recall(key: string): Promise<any> {
|
|
32
|
+
+ return this.store.get(key) ?? null;
|
|
33
|
+
+ }
|
|
34
|
+
|
|
35
|
+
- async recallPattern(key: string): Promise<any> {
|
|
36
|
+
- return this.engine.recall(key);
|
|
37
|
+
+ async learn(_input: any, _feedback: number): Promise<void> {
|
|
38
|
+
+ // Mock: no-op learning without SONA neural backend
|
|
39
|
+
+ }
|
|
40
|
+
+ };
|
|
41
|
+
+ return SonaEngineImpl;
|
|
42
|
+
}
|
|
43
|
+
+}
|
|
44
|
+
|
|
45
|
+
- async learn(input: any, feedback: number): Promise<void> {
|
|
46
|
+
- await this.engine.learn(input, feedback);
|
|
47
|
+
+export class SonaIntegration {
|
|
48
|
+
+ private engine: any = null;
|
|
49
|
+
+ private initialized = false;
|
|
50
|
+
+
|
|
51
|
+
+ private async ensureInit(): Promise<void> {
|
|
52
|
+
+ if (this.initialized) return;
|
|
53
|
+
+ const Engine = await loadSonaEngine();
|
|
54
|
+
+ this.engine = new Engine();
|
|
55
|
+
+ this.initialized = true;
|
|
56
|
+
+ }
|
|
57
|
+
+
|
|
58
|
+
+ async storePattern(key: string, pattern: any): Promise<void> {
|
|
59
|
+
+ await this.ensureInit();
|
|
60
|
+
+ await this.engine.store(key, pattern);
|
|
61
|
+
+ }
|
|
62
|
+
+
|
|
63
|
+
+ async recallPattern(key: string): Promise<any> {
|
|
64
|
+
+ await this.ensureInit();
|
|
65
|
+
+ return this.engine.recall(key);
|
|
66
|
+
+ }
|
|
67
|
+
+
|
|
68
|
+
+ async learn(input: any, feedback: number): Promise<void> {
|
|
69
|
+
+ await this.ensureInit();
|
|
70
|
+
+ await this.engine.learn(input, feedback);
|
|
71
|
+
+ }
|
|
72
|
+
+
|
|
73
|
+
+ isUsingMock(): boolean {
|
|
74
|
+
+ return SonaEngineImpl?.name === 'MockSonaEngine';
|
|
75
|
+
}
|
|
76
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
--- a/npm/packages/agentic-integration/swarm-manager.ts
|
|
2
|
+
+++ b/npm/packages/agentic-integration/swarm-manager.ts
|
|
3
|
+
@@ -1,4 +1,25 @@
|
|
4
|
+
+async function detectClaudeFlowVersion(): Promise<'v2' | 'v3' | null> {
|
|
5
|
+
+ try {
|
|
6
|
+
+ const { stdout } = await execAsync('npx claude-flow --version 2>/dev/null');
|
|
7
|
+
+ const version = stdout.trim();
|
|
8
|
+
+ if (version.startsWith('3.') || version.startsWith('v3.')) return 'v3';
|
|
9
|
+
+ if (version.startsWith('2.') || version.startsWith('v2.') || version.includes('alpha')) return 'v2';
|
|
10
|
+
+ return 'v3'; // default to v3 for newer versions
|
|
11
|
+
+ } catch {
|
|
12
|
+
+ return null;
|
|
13
|
+
+ }
|
|
14
|
+
+}
|
|
15
|
+
+
|
|
16
|
+
async function registerHooks(config: SwarmConfig) {
|
|
17
|
+
- const proc = spawn('npx', ['claude-flow@alpha', 'hooks', 'register', '--swarm', config.name]);
|
|
18
|
+
+ const cfVersion = await detectClaudeFlowVersion();
|
|
19
|
+
+ if (!cfVersion) {
|
|
20
|
+
+ console.warn('[swarm-manager] claude-flow not found, skipping hook registration');
|
|
21
|
+
+ return;
|
|
22
|
+
+ }
|
|
23
|
+
+
|
|
24
|
+
+ const args = cfVersion === 'v3'
|
|
25
|
+
+ ? ['claude-flow', 'mcp', '--hooks', JSON.stringify({ swarm: config.name })]
|
|
26
|
+
+ : ['claude-flow@alpha', 'hooks', 'register', '--swarm', config.name];
|
|
27
|
+
+
|
|
28
|
+
+ const proc = spawn('npx', args);
|
|
29
|
+
// ...
|
|
30
|
+
}
|