claude-flow 3.39.2 → 3.40.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/.claude/proven-config.json +1 -1
- package/node_modules/@claude-flow/codex/dist/cli.js +0 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/bin.js +0 -0
- package/package.json +1 -1
- package/v3/@claude-flow/cli/catalog-manifest.json +3 -3
- package/v3/@claude-flow/cli/dist/src/commands/memory.js +9 -2
- package/v3/@claude-flow/cli/dist/src/log-filters.d.ts +3 -3
- package/v3/@claude-flow/cli/dist/src/mcp-tools/agentbbs-federation.d.ts +178 -0
- package/v3/@claude-flow/cli/dist/src/mcp-tools/agentbbs-federation.js +447 -0
- package/v3/@claude-flow/cli/dist/src/mcp-tools/agentbbs-tools.d.ts +11 -0
- package/v3/@claude-flow/cli/dist/src/mcp-tools/agentbbs-tools.js +191 -31
- package/v3/@claude-flow/cli/dist/src/services/harness-project-anchor.js +16 -5
- package/v3/@claude-flow/cli/package.json +1 -1
- package/v3/@claude-flow/shared/dist/core/config/schema.d.ts +96 -96
- package/.claude/helpers/.helpers-version +0 -1
- package/.claude/helpers/helpers.manifest.json +0 -13
|
File without changes
|
|
File without changes
|
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
3
|
"generation": 6,
|
|
4
|
-
"generatedAt": "2026-09-
|
|
5
|
-
"gitSha": "
|
|
4
|
+
"generatedAt": "2026-09-09T23:09:38.206Z",
|
|
5
|
+
"gitSha": "e111bfbd",
|
|
6
6
|
"catalog": {
|
|
7
7
|
"agents": 167,
|
|
8
|
-
"tools":
|
|
8
|
+
"tools": 402,
|
|
9
9
|
"skills": 34
|
|
10
10
|
},
|
|
11
11
|
"benchmark": null
|
|
@@ -352,7 +352,14 @@ const searchCommand = {
|
|
|
352
352
|
name: 'threshold',
|
|
353
353
|
description: 'Similarity threshold (0-1)',
|
|
354
354
|
type: 'number',
|
|
355
|
-
|
|
355
|
+
// MUST stay <= 0.4. The recall fusion in bridgeSearchEntries scores a
|
|
356
|
+
// full-coverage exact-keyword hit as 0.6*max(0,semantic) + 0.4*lexical,
|
|
357
|
+
// so when the semantic cosine is <= 0 (routine for a one-word query) a
|
|
358
|
+
// perfect keyword match tops out at exactly 0.40. #2790 raised this
|
|
359
|
+
// default to 0.7, which silently re-broke #2558: `memory search` matched
|
|
360
|
+
// content word-for-word and still returned nothing. Regression guard:
|
|
361
|
+
// __tests__/memory-search-recall-2558.test.ts.
|
|
362
|
+
default: 0.3
|
|
356
363
|
},
|
|
357
364
|
{
|
|
358
365
|
name: 'type',
|
|
@@ -421,7 +428,7 @@ const searchCommand = {
|
|
|
421
428
|
// coalescing preserves an explicit zero. Fallback aligned with the
|
|
422
429
|
// option's declared `default: 0.7` (was `0.3` — the two disagreed
|
|
423
430
|
// and --help advertised a default the code did not honor).
|
|
424
|
-
const threshold = ctx.flags.threshold ?? 0.
|
|
431
|
+
const threshold = ctx.flags.threshold ?? 0.3;
|
|
425
432
|
const searchType = ctx.flags.type || 'semantic';
|
|
426
433
|
const buildHnsw = (ctx.flags['build-hnsw'] || ctx.flags.buildHnsw);
|
|
427
434
|
const requestedIntent = ctx.flags.intent || 'mixed';
|
|
@@ -40,7 +40,7 @@ declare const STDERR_REDIRECT_PREFIXES: string[];
|
|
|
40
40
|
declare const AGENTDB_MOCK_FALLBACK_DROP_PREFIXES: string[];
|
|
41
41
|
declare const shouldRedirectToStderr: (msg: unknown) => boolean;
|
|
42
42
|
declare const isAgentdbMockFallbackNoise: (msg: unknown) => boolean;
|
|
43
|
-
declare const origWarn: (...
|
|
44
|
-
declare const origLog: (...
|
|
45
|
-
declare const origError: (...
|
|
43
|
+
declare const origWarn: (message?: any, ...optionalParams: any[]) => void;
|
|
44
|
+
declare const origLog: (message?: any, ...optionalParams: any[]) => void;
|
|
45
|
+
declare const origError: (message?: any, ...optionalParams: any[]) => void;
|
|
46
46
|
//# sourceMappingURL=log-filters.d.ts.map
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* agentbbs Phase 2 — cross-host federation.
|
|
3
|
+
*
|
|
4
|
+
* Phase 1 (`agentbbs-tools.ts`) gives every host an append-only room log at
|
|
5
|
+
* `<basePath>/room-<roomId>.jsonl`, and derives `roomId` deterministically from
|
|
6
|
+
* the room label. Two independent hosts that register `#sales` therefore
|
|
7
|
+
* compute the *same* roomId without ever talking to each other. That is the
|
|
8
|
+
* property this module builds on.
|
|
9
|
+
*
|
|
10
|
+
* ## Why a signed union-merge, and not a consensus protocol
|
|
11
|
+
*
|
|
12
|
+
* A room log is an append-only set of immutable envelopes. Two hosts that each
|
|
13
|
+
* append locally hold two subsets of the same logical set, so reconciling them
|
|
14
|
+
* is a set union — there is no conflicting write to arbitrate, and therefore
|
|
15
|
+
* nothing for a consensus round to decide. Union is commutative, associative
|
|
16
|
+
* and idempotent, which makes sync order-independent and safe to retry: pulling
|
|
17
|
+
* the same peer twice, or pulling A-then-B versus B-then-A, converges on the
|
|
18
|
+
* same log. That is a CRDT (a grow-only set keyed by `envelopeId`), and it is
|
|
19
|
+
* strictly cheaper and less failure-prone than the Byzantine agreement the
|
|
20
|
+
* plugin README gestures at.
|
|
21
|
+
*
|
|
22
|
+
* What union does *not* give you is authenticity. If any peer can inject an
|
|
23
|
+
* envelope, the merge faithfully replicates forgeries. So every envelope is
|
|
24
|
+
* Ed25519-signed by its originating node, and a receiver verifies the signature
|
|
25
|
+
* against the *pinned* public key it recorded when the peer was added — not
|
|
26
|
+
* against a key carried in the envelope, which would let an attacker sign with
|
|
27
|
+
* their own key and claim any origin. Trust is pinned at peer-add time; the
|
|
28
|
+
* wire is treated as hostile.
|
|
29
|
+
*
|
|
30
|
+
* ## Transport
|
|
31
|
+
*
|
|
32
|
+
* Pull-based HTTP. A node serves `GET /agentbbs/v1/rooms/:roomId/envelopes?since=N`
|
|
33
|
+
* and peers poll it. Pull is deliberate: it needs no inbound connectivity from
|
|
34
|
+
* the peer's side, survives a node being offline (it just catches up later),
|
|
35
|
+
* and gives the *receiver* control over how much it ingests. Push would invert
|
|
36
|
+
* that and make every node an unauthenticated write target.
|
|
37
|
+
*
|
|
38
|
+
* Designed for a private overlay (Tailscale/WireGuard) where the network
|
|
39
|
+
* already authenticates the host. Signatures mean a compromised or hostile peer
|
|
40
|
+
* still cannot forge another node's envelopes. See `bindHost` on serve() — it
|
|
41
|
+
* binds loopback by default, and binding a routable interface is an explicit
|
|
42
|
+
* operator choice.
|
|
43
|
+
*
|
|
44
|
+
* ## Bounds
|
|
45
|
+
*
|
|
46
|
+
* Every ingest path is bounded: envelope count per sync, byte size per envelope,
|
|
47
|
+
* total bytes per response, peer count, and hop count. An unbounded merge from
|
|
48
|
+
* an untrusted peer is a memory-exhaustion primitive, so limits are enforced on
|
|
49
|
+
* the *receiving* side where they cannot be negotiated away by the sender.
|
|
50
|
+
*
|
|
51
|
+
* @module @claude-flow/cli/mcp-tools/agentbbs-federation
|
|
52
|
+
*/
|
|
53
|
+
import { type Server } from 'node:http';
|
|
54
|
+
/** Max envelopes accepted from one peer in one sync. */
|
|
55
|
+
export declare const MAX_ENVELOPES_PER_SYNC = 5000;
|
|
56
|
+
/** Max serialized bytes for a single envelope. */
|
|
57
|
+
export declare const MAX_ENVELOPE_BYTES: number;
|
|
58
|
+
/** Max total bytes read from one peer response. */
|
|
59
|
+
export declare const MAX_SYNC_RESPONSE_BYTES: number;
|
|
60
|
+
/** Max peers in the registry. */
|
|
61
|
+
export declare const MAX_PEERS = 256;
|
|
62
|
+
/** Max federation hops before an envelope stops propagating. */
|
|
63
|
+
export declare const MAX_HOPS = 8;
|
|
64
|
+
/** Per-request timeout when pulling from a peer. */
|
|
65
|
+
export declare const SYNC_TIMEOUT_MS = 15000;
|
|
66
|
+
export interface NodeIdentity {
|
|
67
|
+
nodeId: string;
|
|
68
|
+
publicKey: string;
|
|
69
|
+
privateKey: string;
|
|
70
|
+
createdAt: string;
|
|
71
|
+
}
|
|
72
|
+
export interface FederationPeer {
|
|
73
|
+
nodeId: string;
|
|
74
|
+
url: string;
|
|
75
|
+
publicKey: string;
|
|
76
|
+
label?: string;
|
|
77
|
+
addedAt: string;
|
|
78
|
+
lastSyncedAt?: string;
|
|
79
|
+
lastSeq?: Record<string, number>;
|
|
80
|
+
}
|
|
81
|
+
export interface SignedEnvelope {
|
|
82
|
+
envelopeId: string;
|
|
83
|
+
roomId: string;
|
|
84
|
+
seq: number;
|
|
85
|
+
msgType: string;
|
|
86
|
+
payload: unknown;
|
|
87
|
+
timestamp: string;
|
|
88
|
+
origin?: string;
|
|
89
|
+
hops?: number;
|
|
90
|
+
signature?: string;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Deterministic byte string an envelope's signature covers.
|
|
94
|
+
*
|
|
95
|
+
* Field order is fixed here rather than relying on `JSON.stringify` key order,
|
|
96
|
+
* because a receiver must reconstruct byte-identical input from a payload that
|
|
97
|
+
* survived a JSON round trip. `payload` is canonicalized recursively with
|
|
98
|
+
* sorted keys for the same reason: `{a:1,b:2}` and `{b:2,a:1}` are the same
|
|
99
|
+
* value and must not produce different signatures.
|
|
100
|
+
*
|
|
101
|
+
* `hops` is deliberately excluded — it is mutated in transit by design, so
|
|
102
|
+
* including it would invalidate the signature at the first relay.
|
|
103
|
+
*/
|
|
104
|
+
export declare function canonicalEnvelopeBytes(env: SignedEnvelope): Uint8Array;
|
|
105
|
+
/**
|
|
106
|
+
* Load or create this host's long-lived Ed25519 identity.
|
|
107
|
+
*
|
|
108
|
+
* Phase 1 minted an ephemeral key per process, which is fine for local token
|
|
109
|
+
* signing but useless across hosts: a peer cannot pin a key that changes on
|
|
110
|
+
* every restart. This persists one, 0600, and derives a stable nodeId from the
|
|
111
|
+
* public key so identity is verifiable rather than self-asserted.
|
|
112
|
+
*/
|
|
113
|
+
export declare function getNodeIdentity(basePath: string): Promise<NodeIdentity>;
|
|
114
|
+
export declare function signEnvelope(basePath: string, env: SignedEnvelope): Promise<SignedEnvelope>;
|
|
115
|
+
/**
|
|
116
|
+
* Verify an envelope against a public key the caller already trusts.
|
|
117
|
+
*
|
|
118
|
+
* The key is passed in rather than read from the envelope on purpose: an
|
|
119
|
+
* envelope-carried key proves only that the sender holds *a* key, not that they
|
|
120
|
+
* are who the `origin` field claims. Callers pass the key pinned at peer-add.
|
|
121
|
+
*/
|
|
122
|
+
export declare function verifyEnvelope(env: SignedEnvelope, publicKeyHex: string): Promise<boolean>;
|
|
123
|
+
export declare function readPeers(basePath: string): FederationPeer[];
|
|
124
|
+
/**
|
|
125
|
+
* Reject anything that is not a plain http(s) URL to a host.
|
|
126
|
+
*
|
|
127
|
+
* Blocks credentials-in-URL (they would be logged), and non-http schemes such
|
|
128
|
+
* as `file:` which would turn a peer entry into a local file read.
|
|
129
|
+
*/
|
|
130
|
+
export declare function validatePeerUrl(raw: string): string;
|
|
131
|
+
export declare function addPeer(basePath: string, input: {
|
|
132
|
+
nodeId: string;
|
|
133
|
+
url: string;
|
|
134
|
+
publicKey: string;
|
|
135
|
+
label?: string;
|
|
136
|
+
}): FederationPeer;
|
|
137
|
+
export declare function removePeer(basePath: string, nodeId: string): boolean;
|
|
138
|
+
export declare function readEnvelopes(basePath: string, roomId: string): SignedEnvelope[];
|
|
139
|
+
export declare function validateRoomId(roomId: string): string;
|
|
140
|
+
export interface MergeResult {
|
|
141
|
+
merged: number;
|
|
142
|
+
skippedDuplicate: number;
|
|
143
|
+
skippedUnverified: number;
|
|
144
|
+
skippedOversize: number;
|
|
145
|
+
skippedHopLimit: number;
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Union-merge verified envelopes from a peer into the local room log.
|
|
149
|
+
*
|
|
150
|
+
* Idempotent: `envelopeId` is the merge key, so replaying the same batch is a
|
|
151
|
+
* no-op. Anything that fails verification is dropped and counted rather than
|
|
152
|
+
* quarantined — a receiver has no use for an envelope it cannot attribute.
|
|
153
|
+
*/
|
|
154
|
+
export declare function mergeEnvelopes(basePath: string, roomId: string, incoming: SignedEnvelope[], peerPublicKey: string): Promise<MergeResult>;
|
|
155
|
+
/** Pull one room from one peer and merge what verifies. */
|
|
156
|
+
export declare function syncRoomFromPeer(basePath: string, peer: FederationPeer, roomId: string, fetchImpl?: typeof fetch): Promise<MergeResult & {
|
|
157
|
+
peerNodeId: string;
|
|
158
|
+
roomId: string;
|
|
159
|
+
}>;
|
|
160
|
+
/**
|
|
161
|
+
* Serve this node's room logs for peers to pull.
|
|
162
|
+
*
|
|
163
|
+
* Binds loopback unless the caller explicitly asks otherwise, so starting a
|
|
164
|
+
* server never silently exposes room contents on a routable interface. Read
|
|
165
|
+
* only by construction: there is no route that mutates state, which removes the
|
|
166
|
+
* whole class of unauthenticated-write attacks that a push design would open.
|
|
167
|
+
*/
|
|
168
|
+
export declare function serveFederation(basePath: string, opts?: {
|
|
169
|
+
port?: number;
|
|
170
|
+
bindHost?: string;
|
|
171
|
+
}): Promise<{
|
|
172
|
+
server: Server;
|
|
173
|
+
port: number;
|
|
174
|
+
host: string;
|
|
175
|
+
}>;
|
|
176
|
+
/** Constant-time compare for any future shared-secret paths. */
|
|
177
|
+
export declare function safeEqual(a: string, b: string): boolean;
|
|
178
|
+
//# sourceMappingURL=agentbbs-federation.d.ts.map
|