@browserbridge/bbx 1.6.3 → 1.6.4
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
|
@@ -132,6 +132,67 @@ export function summarizeToolError(error) {
|
|
|
132
132
|
);
|
|
133
133
|
}
|
|
134
134
|
|
|
135
|
+
/**
|
|
136
|
+
* @param {ToolResult} result
|
|
137
|
+
* @returns {boolean}
|
|
138
|
+
*/
|
|
139
|
+
function shouldTryRemoteFallback(result) {
|
|
140
|
+
if (!result.isError && result.structuredContent.ok !== false) {
|
|
141
|
+
return false;
|
|
142
|
+
}
|
|
143
|
+
const text = result.content[0]?.text ?? '';
|
|
144
|
+
return /\b(ACCESS_DENIED|DAEMON_OFFLINE|EXTENSION_DISCONNECTED|NATIVE_HOST_UNAVAILABLE|CONNECTION_LOST)\b|\b(ENOENT|ECONNREFUSED|ETIMEDOUT)\b|ERROR: connect\b/u.test(
|
|
145
|
+
text
|
|
146
|
+
);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* @param {ToolResult} result
|
|
151
|
+
* @param {string} destinationId
|
|
152
|
+
* @returns {ToolResult}
|
|
153
|
+
*/
|
|
154
|
+
function annotateAutoDestination(result, destinationId) {
|
|
155
|
+
return {
|
|
156
|
+
...result,
|
|
157
|
+
structuredContent: {
|
|
158
|
+
...result.structuredContent,
|
|
159
|
+
destinationId,
|
|
160
|
+
autoSelectedDestinationId: destinationId,
|
|
161
|
+
},
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* @param {(client: import('../../agent-client/src/client.js').BridgeClient) => Promise<ToolResult>} callback
|
|
167
|
+
* @param {ToolResult} localResult
|
|
168
|
+
* @returns {Promise<ToolResult>}
|
|
169
|
+
*/
|
|
170
|
+
async function tryRemoteFallback(callback, localResult) {
|
|
171
|
+
const remotes = (await listBridgeDestinations()).filter((destination) => !destination.local);
|
|
172
|
+
if (remotes.length === 0) {
|
|
173
|
+
return localResult;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
let lastFallbackResult = localResult;
|
|
177
|
+
for (const remote of remotes) {
|
|
178
|
+
const client = await createBridgeClientForDestination(remote.id);
|
|
179
|
+
try {
|
|
180
|
+
await client.connect();
|
|
181
|
+
const result = annotateAutoDestination(await callback(client), remote.id);
|
|
182
|
+
lastFallbackResult = result;
|
|
183
|
+
if (!shouldTryRemoteFallback(result)) {
|
|
184
|
+
return result;
|
|
185
|
+
}
|
|
186
|
+
} catch (error) {
|
|
187
|
+
lastFallbackResult = annotateAutoDestination(summarizeToolError(error), remote.id);
|
|
188
|
+
} finally {
|
|
189
|
+
await client.close();
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
return lastFallbackResult;
|
|
194
|
+
}
|
|
195
|
+
|
|
135
196
|
/**
|
|
136
197
|
* @param {(client: import('../../agent-client/src/client.js').BridgeClient) => Promise<ToolResult>} callback
|
|
137
198
|
* @param {{ destinationId?: string | null }} [options]
|
|
@@ -140,7 +201,8 @@ export function summarizeToolError(error) {
|
|
|
140
201
|
export async function withToolClient(callback, options = {}) {
|
|
141
202
|
try {
|
|
142
203
|
if (!options.destinationId) {
|
|
143
|
-
|
|
204
|
+
const result = await withBridgeClient(callback);
|
|
205
|
+
return shouldTryRemoteFallback(result) ? await tryRemoteFallback(callback, result) : result;
|
|
144
206
|
}
|
|
145
207
|
const client = await createBridgeClientForDestination(options.destinationId);
|
|
146
208
|
await client.connect();
|
|
@@ -67,10 +67,31 @@ export {
|
|
|
67
67
|
const HOME_DIR = os.homedir();
|
|
68
68
|
|
|
69
69
|
/**
|
|
70
|
+
* @param {{ destinationId?: string }} [args]
|
|
70
71
|
* @returns {Promise<ToolResult>}
|
|
71
72
|
*/
|
|
72
|
-
export async function handleStatusTool() {
|
|
73
|
+
export async function handleStatusTool(args = {}) {
|
|
73
74
|
try {
|
|
75
|
+
const requestedDestinationId =
|
|
76
|
+
typeof args.destinationId === 'string' ? args.destinationId : null;
|
|
77
|
+
if (requestedDestinationId && requestedDestinationId !== 'local') {
|
|
78
|
+
const destination = (await getBridgeDestinations()).find(
|
|
79
|
+
(entry) => entry.id === requestedDestinationId
|
|
80
|
+
);
|
|
81
|
+
const result = await callRemoteHealth(requestedDestinationId);
|
|
82
|
+
return createToolResult(
|
|
83
|
+
result.reachable
|
|
84
|
+
? `Browser Bridge destination "${requestedDestinationId}" is reachable.`
|
|
85
|
+
: `Browser Bridge destination "${requestedDestinationId}" is not reachable.`,
|
|
86
|
+
{
|
|
87
|
+
ok: result.reachable === true,
|
|
88
|
+
destination: destination ?? { id: requestedDestinationId, local: false },
|
|
89
|
+
...result,
|
|
90
|
+
},
|
|
91
|
+
result.reachable !== true
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
|
|
74
95
|
const report = await getDoctorReport();
|
|
75
96
|
const destinations = await Promise.all(
|
|
76
97
|
(await getBridgeDestinations()).map(async (destination) => {
|