@openscout/runtime 0.2.29 → 0.2.31
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/dist/broker-daemon.js +26 -1
- package/dist/mesh-discovery.js +4 -0
- package/dist/mesh-forwarding.d.ts +1 -0
- package/dist/mesh-forwarding.js +11 -0
- package/package.json +2 -2
- package/src/broker-daemon.ts +24 -0
- package/src/mesh-discovery.ts +3 -0
- package/src/mesh-forwarding.ts +13 -0
package/dist/broker-daemon.js
CHANGED
|
@@ -6,7 +6,7 @@ import { createInMemoryControlRuntime } from "./broker.js";
|
|
|
6
6
|
import { FileBackedBrokerJournal } from "./broker-journal.js";
|
|
7
7
|
import { buildCollaborationInvocation } from "./collaboration-invocations.js";
|
|
8
8
|
import { discoverMeshNodes } from "./mesh-discovery.js";
|
|
9
|
-
import { buildMeshCollaborationEventBundle, buildMeshCollaborationRecordBundle, buildMeshInvocationBundle, buildMeshMessageBundle, forwardMeshCollaborationEvent, forwardMeshCollaborationRecord, forwardMeshInvocation, forwardMeshMessage, } from "./mesh-forwarding.js";
|
|
9
|
+
import { buildMeshCollaborationEventBundle, buildMeshCollaborationRecordBundle, buildMeshInvocationBundle, buildMeshMessageBundle, forwardMeshCollaborationEvent, forwardMeshCollaborationRecord, forwardMeshInvocation, fetchPeerAgents, forwardMeshMessage, } from "./mesh-forwarding.js";
|
|
10
10
|
import { ensureLocalAgentBindingOnline, isLocalAgentEndpointAlive, isLocalAgentSessionAlive, invokeLocalAgentEndpoint, loadRegisteredLocalAgentBindings, shouldDisableGeneratedCodexEndpoint, } from "./local-agents.js";
|
|
11
11
|
import { RecoverableSQLiteProjection } from "./sqlite-projection.js";
|
|
12
12
|
import { ensureOpenScoutCleanSlateSync } from "./support-paths.js";
|
|
@@ -144,6 +144,31 @@ async function discoverPeers(seeds = []) {
|
|
|
144
144
|
for (const node of result.discovered) {
|
|
145
145
|
await upsertNodeDurably(node);
|
|
146
146
|
}
|
|
147
|
+
// Sync agents from each discovered peer so local broker knows about remote agents.
|
|
148
|
+
// This enables @mention resolution and message forwarding across the mesh.
|
|
149
|
+
for (const node of result.discovered) {
|
|
150
|
+
if (!node.brokerUrl)
|
|
151
|
+
continue;
|
|
152
|
+
try {
|
|
153
|
+
const peerAgents = await fetchPeerAgents(node.brokerUrl);
|
|
154
|
+
for (const agent of peerAgents) {
|
|
155
|
+
if (agent.id === nodeId)
|
|
156
|
+
continue;
|
|
157
|
+
const remoteAgent = {
|
|
158
|
+
...agent,
|
|
159
|
+
homeNodeId: agent.homeNodeId || node.id,
|
|
160
|
+
authorityNodeId: agent.authorityNodeId || node.id,
|
|
161
|
+
};
|
|
162
|
+
await upsertAgentDurably(remoteAgent);
|
|
163
|
+
}
|
|
164
|
+
if (peerAgents.length > 0) {
|
|
165
|
+
console.log(`[openscout-runtime] synced ${peerAgents.length} agent(s) from peer ${node.name || node.id}`);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
catch {
|
|
169
|
+
// Best-effort: peer may be temporarily unreachable
|
|
170
|
+
}
|
|
171
|
+
}
|
|
147
172
|
return result.discovered;
|
|
148
173
|
}
|
|
149
174
|
function currentLocalNode() {
|
package/dist/mesh-discovery.js
CHANGED
|
@@ -58,6 +58,7 @@ export async function discoverMeshNodes(options) {
|
|
|
58
58
|
const candidates = unique([...peerSeeds, ...tailscaleSeeds])
|
|
59
59
|
.filter((seed) => seed && seed !== options.localBrokerUrl);
|
|
60
60
|
const discovered = [];
|
|
61
|
+
const seen = new Set();
|
|
61
62
|
for (const seed of candidates) {
|
|
62
63
|
const node = await probeNode(seed, options.timeoutMs ?? 1500);
|
|
63
64
|
if (!node)
|
|
@@ -66,6 +67,9 @@ export async function discoverMeshNodes(options) {
|
|
|
66
67
|
continue;
|
|
67
68
|
if (node.meshId !== options.meshId)
|
|
68
69
|
continue;
|
|
70
|
+
if (seen.has(node.id))
|
|
71
|
+
continue;
|
|
72
|
+
seen.add(node.id);
|
|
69
73
|
discovered.push({
|
|
70
74
|
...node,
|
|
71
75
|
brokerUrl: node.brokerUrl ?? seed,
|
package/dist/mesh-forwarding.js
CHANGED
|
@@ -179,3 +179,14 @@ export async function forwardMeshCollaborationRecord(brokerUrl, bundle) {
|
|
|
179
179
|
export async function forwardMeshCollaborationEvent(brokerUrl, bundle) {
|
|
180
180
|
return postJson(`${brokerUrl.replace(/\/$/, "")}/v1/mesh/collaboration/events`, bundle);
|
|
181
181
|
}
|
|
182
|
+
export async function fetchPeerAgents(brokerUrl) {
|
|
183
|
+
const url = `${brokerUrl.replace(/\/$/, "")}/v1/snapshot`;
|
|
184
|
+
const response = await fetch(url, {
|
|
185
|
+
headers: { accept: "application/json" },
|
|
186
|
+
signal: AbortSignal.timeout(5_000),
|
|
187
|
+
});
|
|
188
|
+
if (!response.ok)
|
|
189
|
+
return [];
|
|
190
|
+
const snapshot = await response.json();
|
|
191
|
+
return Object.values(snapshot.agents ?? {});
|
|
192
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openscout/runtime",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.31",
|
|
4
4
|
"description": "Local runtime foundation for the OpenScout control plane",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -86,7 +86,7 @@
|
|
|
86
86
|
"postpack": "node ../../scripts/restore-publish-manifest.mjs ."
|
|
87
87
|
},
|
|
88
88
|
"dependencies": {
|
|
89
|
-
"@openscout/protocol": "0.2.
|
|
89
|
+
"@openscout/protocol": "0.2.31",
|
|
90
90
|
"smol-toml": "^1.6.1"
|
|
91
91
|
},
|
|
92
92
|
"publishConfig": {
|
package/src/broker-daemon.ts
CHANGED
|
@@ -34,6 +34,7 @@ import {
|
|
|
34
34
|
forwardMeshCollaborationEvent,
|
|
35
35
|
forwardMeshCollaborationRecord,
|
|
36
36
|
forwardMeshInvocation,
|
|
37
|
+
fetchPeerAgents,
|
|
37
38
|
forwardMeshMessage,
|
|
38
39
|
type MeshCollaborationEventBundle,
|
|
39
40
|
type MeshCollaborationRecordBundle,
|
|
@@ -220,6 +221,29 @@ async function discoverPeers(seeds: string[] = []): Promise<NodeDefinition[]> {
|
|
|
220
221
|
await upsertNodeDurably(node);
|
|
221
222
|
}
|
|
222
223
|
|
|
224
|
+
// Sync agents from each discovered peer so local broker knows about remote agents.
|
|
225
|
+
// This enables @mention resolution and message forwarding across the mesh.
|
|
226
|
+
for (const node of result.discovered) {
|
|
227
|
+
if (!node.brokerUrl) continue;
|
|
228
|
+
try {
|
|
229
|
+
const peerAgents = await fetchPeerAgents(node.brokerUrl);
|
|
230
|
+
for (const agent of peerAgents) {
|
|
231
|
+
if (agent.id === nodeId) continue;
|
|
232
|
+
const remoteAgent: AgentDefinition = {
|
|
233
|
+
...agent,
|
|
234
|
+
homeNodeId: agent.homeNodeId || node.id,
|
|
235
|
+
authorityNodeId: agent.authorityNodeId || node.id,
|
|
236
|
+
};
|
|
237
|
+
await upsertAgentDurably(remoteAgent);
|
|
238
|
+
}
|
|
239
|
+
if (peerAgents.length > 0) {
|
|
240
|
+
console.log(`[openscout-runtime] synced ${peerAgents.length} agent(s) from peer ${node.name || node.id}`);
|
|
241
|
+
}
|
|
242
|
+
} catch {
|
|
243
|
+
// Best-effort: peer may be temporarily unreachable
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
223
247
|
return result.discovered;
|
|
224
248
|
}
|
|
225
249
|
|
package/src/mesh-discovery.ts
CHANGED
|
@@ -82,12 +82,15 @@ export async function discoverMeshNodes(
|
|
|
82
82
|
.filter((seed) => seed && seed !== options.localBrokerUrl);
|
|
83
83
|
|
|
84
84
|
const discovered: NodeDefinition[] = [];
|
|
85
|
+
const seen = new Set<string>();
|
|
85
86
|
|
|
86
87
|
for (const seed of candidates) {
|
|
87
88
|
const node = await probeNode(seed, options.timeoutMs ?? 1500);
|
|
88
89
|
if (!node) continue;
|
|
89
90
|
if (node.id === options.localNodeId) continue;
|
|
90
91
|
if (node.meshId !== options.meshId) continue;
|
|
92
|
+
if (seen.has(node.id)) continue;
|
|
93
|
+
seen.add(node.id);
|
|
91
94
|
|
|
92
95
|
discovered.push({
|
|
93
96
|
...node,
|
package/src/mesh-forwarding.ts
CHANGED
|
@@ -297,3 +297,16 @@ export async function forwardMeshCollaborationEvent(
|
|
|
297
297
|
): Promise<{ ok: true; duplicate?: boolean }> {
|
|
298
298
|
return postJson(`${brokerUrl.replace(/\/$/, "")}/v1/mesh/collaboration/events`, bundle);
|
|
299
299
|
}
|
|
300
|
+
|
|
301
|
+
export async function fetchPeerAgents(
|
|
302
|
+
brokerUrl: string,
|
|
303
|
+
): Promise<AgentDefinition[]> {
|
|
304
|
+
const url = `${brokerUrl.replace(/\/$/, "")}/v1/snapshot`;
|
|
305
|
+
const response = await fetch(url, {
|
|
306
|
+
headers: { accept: "application/json" },
|
|
307
|
+
signal: AbortSignal.timeout(5_000),
|
|
308
|
+
});
|
|
309
|
+
if (!response.ok) return [];
|
|
310
|
+
const snapshot = await response.json() as { agents?: Record<string, AgentDefinition> };
|
|
311
|
+
return Object.values(snapshot.agents ?? {});
|
|
312
|
+
}
|