@react-grab/amp 0.1.0-beta.8 → 0.1.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/dist/cli.cjs +34 -9
- package/dist/cli.js +34 -9
- package/dist/client.cjs +14 -7
- package/dist/client.global.js +449 -2
- package/dist/client.js +14 -7
- package/package.json +13 -13
package/dist/cli.cjs
CHANGED
|
@@ -4945,8 +4945,13 @@ ${context.content.join("\n\n")}`;
|
|
|
4945
4945
|
signal
|
|
4946
4946
|
})) {
|
|
4947
4947
|
if (signal.aborted) break;
|
|
4948
|
+
const getBrowserMessageType = (messageType) => {
|
|
4949
|
+
if (messageType === "status") return "agent-status";
|
|
4950
|
+
if (messageType === "error") return "agent-error";
|
|
4951
|
+
return "agent-done";
|
|
4952
|
+
};
|
|
4948
4953
|
sendToBrowser(browserSocket, {
|
|
4949
|
-
type: message.type
|
|
4954
|
+
type: getBrowserMessageType(message.type),
|
|
4950
4955
|
agentId: handler.agentId,
|
|
4951
4956
|
sessionId,
|
|
4952
4957
|
content: message.content
|
|
@@ -5149,9 +5154,13 @@ ${context.content.join("\n\n")}`;
|
|
|
5149
5154
|
} else if (message.type === "agent-status" || message.type === "agent-done" || message.type === "agent-error") {
|
|
5150
5155
|
const messageQueue = sessionMessageQueues.get(message.sessionId);
|
|
5151
5156
|
if (messageQueue) {
|
|
5152
|
-
const
|
|
5157
|
+
const getQueueMessageType = (handlerMessageType) => {
|
|
5158
|
+
if (handlerMessageType === "agent-status") return "status";
|
|
5159
|
+
if (handlerMessageType === "agent-done") return "done";
|
|
5160
|
+
return "error";
|
|
5161
|
+
};
|
|
5153
5162
|
messageQueue.push({
|
|
5154
|
-
type:
|
|
5163
|
+
type: getQueueMessageType(message.type),
|
|
5155
5164
|
content: message.content ?? ""
|
|
5156
5165
|
});
|
|
5157
5166
|
if (message.type === "agent-done" || message.type === "agent-error") {
|
|
@@ -5174,7 +5183,12 @@ ${context.content.join("\n\n")}`;
|
|
|
5174
5183
|
}
|
|
5175
5184
|
}
|
|
5176
5185
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
5177
|
-
res.end(
|
|
5186
|
+
res.end(
|
|
5187
|
+
JSON.stringify({
|
|
5188
|
+
status: "ok",
|
|
5189
|
+
handlers: getRegisteredHandlerIds()
|
|
5190
|
+
})
|
|
5191
|
+
);
|
|
5178
5192
|
return;
|
|
5179
5193
|
}
|
|
5180
5194
|
res.writeHead(404);
|
|
@@ -5189,7 +5203,10 @@ ${context.content.join("\n\n")}`;
|
|
|
5189
5203
|
});
|
|
5190
5204
|
webSocketServer.on("connection", (socket, request) => {
|
|
5191
5205
|
if (token) {
|
|
5192
|
-
const connectionUrl = new URL(
|
|
5206
|
+
const connectionUrl = new URL(
|
|
5207
|
+
request.url ?? "",
|
|
5208
|
+
`http://localhost:${port}`
|
|
5209
|
+
);
|
|
5193
5210
|
const clientToken = connectionUrl.searchParams.get(RELAY_TOKEN_PARAM);
|
|
5194
5211
|
if (clientToken !== token) {
|
|
5195
5212
|
socket.close(4001, "Unauthorized");
|
|
@@ -5230,7 +5247,9 @@ ${context.content.join("\n\n")}`;
|
|
|
5230
5247
|
});
|
|
5231
5248
|
socket.on("message", (data) => {
|
|
5232
5249
|
try {
|
|
5233
|
-
const message = JSON.parse(
|
|
5250
|
+
const message = JSON.parse(
|
|
5251
|
+
data.toString()
|
|
5252
|
+
);
|
|
5234
5253
|
handleBrowserMessage(socket, message);
|
|
5235
5254
|
} catch {
|
|
5236
5255
|
}
|
|
@@ -5275,7 +5294,10 @@ ${context.content.join("\n\n")}`;
|
|
|
5275
5294
|
httpServer?.close();
|
|
5276
5295
|
};
|
|
5277
5296
|
const registerHandler = (handler) => {
|
|
5278
|
-
registeredHandlers.set(handler.agentId, {
|
|
5297
|
+
registeredHandlers.set(handler.agentId, {
|
|
5298
|
+
agentId: handler.agentId,
|
|
5299
|
+
handler
|
|
5300
|
+
});
|
|
5279
5301
|
broadcastHandlerList();
|
|
5280
5302
|
};
|
|
5281
5303
|
const unregisterHandler = (agentId) => {
|
|
@@ -7836,7 +7858,7 @@ async function fkill(inputs, options = {}) {
|
|
|
7836
7858
|
}
|
|
7837
7859
|
}
|
|
7838
7860
|
var sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
7839
|
-
var VERSION = "0.1.0
|
|
7861
|
+
var VERSION = "0.1.0";
|
|
7840
7862
|
var checkIfRelayServerIsRunning = async (port, token) => {
|
|
7841
7863
|
try {
|
|
7842
7864
|
const healthUrl = token ? `http://localhost:${port}/health?${RELAY_TOKEN_PARAM}=${encodeURIComponent(token)}` : `http://localhost:${port}/health`;
|
|
@@ -7854,7 +7876,10 @@ var connectRelay = async (options) => {
|
|
|
7854
7876
|
const { handler, token } = options;
|
|
7855
7877
|
let relayServer = null;
|
|
7856
7878
|
let isRelayHost = false;
|
|
7857
|
-
const isRelayServerRunning = await checkIfRelayServerIsRunning(
|
|
7879
|
+
const isRelayServerRunning = await checkIfRelayServerIsRunning(
|
|
7880
|
+
relayPort,
|
|
7881
|
+
token
|
|
7882
|
+
);
|
|
7858
7883
|
if (isRelayServerRunning) {
|
|
7859
7884
|
relayServer = await connectToExistingRelay(relayPort, handler, token);
|
|
7860
7885
|
} else {
|
package/dist/cli.js
CHANGED
|
@@ -4934,8 +4934,13 @@ ${context.content.join("\n\n")}`;
|
|
|
4934
4934
|
signal
|
|
4935
4935
|
})) {
|
|
4936
4936
|
if (signal.aborted) break;
|
|
4937
|
+
const getBrowserMessageType = (messageType) => {
|
|
4938
|
+
if (messageType === "status") return "agent-status";
|
|
4939
|
+
if (messageType === "error") return "agent-error";
|
|
4940
|
+
return "agent-done";
|
|
4941
|
+
};
|
|
4937
4942
|
sendToBrowser(browserSocket, {
|
|
4938
|
-
type: message.type
|
|
4943
|
+
type: getBrowserMessageType(message.type),
|
|
4939
4944
|
agentId: handler.agentId,
|
|
4940
4945
|
sessionId,
|
|
4941
4946
|
content: message.content
|
|
@@ -5138,9 +5143,13 @@ ${context.content.join("\n\n")}`;
|
|
|
5138
5143
|
} else if (message.type === "agent-status" || message.type === "agent-done" || message.type === "agent-error") {
|
|
5139
5144
|
const messageQueue = sessionMessageQueues.get(message.sessionId);
|
|
5140
5145
|
if (messageQueue) {
|
|
5141
|
-
const
|
|
5146
|
+
const getQueueMessageType = (handlerMessageType) => {
|
|
5147
|
+
if (handlerMessageType === "agent-status") return "status";
|
|
5148
|
+
if (handlerMessageType === "agent-done") return "done";
|
|
5149
|
+
return "error";
|
|
5150
|
+
};
|
|
5142
5151
|
messageQueue.push({
|
|
5143
|
-
type:
|
|
5152
|
+
type: getQueueMessageType(message.type),
|
|
5144
5153
|
content: message.content ?? ""
|
|
5145
5154
|
});
|
|
5146
5155
|
if (message.type === "agent-done" || message.type === "agent-error") {
|
|
@@ -5163,7 +5172,12 @@ ${context.content.join("\n\n")}`;
|
|
|
5163
5172
|
}
|
|
5164
5173
|
}
|
|
5165
5174
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
5166
|
-
res.end(
|
|
5175
|
+
res.end(
|
|
5176
|
+
JSON.stringify({
|
|
5177
|
+
status: "ok",
|
|
5178
|
+
handlers: getRegisteredHandlerIds()
|
|
5179
|
+
})
|
|
5180
|
+
);
|
|
5167
5181
|
return;
|
|
5168
5182
|
}
|
|
5169
5183
|
res.writeHead(404);
|
|
@@ -5178,7 +5192,10 @@ ${context.content.join("\n\n")}`;
|
|
|
5178
5192
|
});
|
|
5179
5193
|
webSocketServer.on("connection", (socket, request) => {
|
|
5180
5194
|
if (token) {
|
|
5181
|
-
const connectionUrl = new URL(
|
|
5195
|
+
const connectionUrl = new URL(
|
|
5196
|
+
request.url ?? "",
|
|
5197
|
+
`http://localhost:${port}`
|
|
5198
|
+
);
|
|
5182
5199
|
const clientToken = connectionUrl.searchParams.get(RELAY_TOKEN_PARAM);
|
|
5183
5200
|
if (clientToken !== token) {
|
|
5184
5201
|
socket.close(4001, "Unauthorized");
|
|
@@ -5219,7 +5236,9 @@ ${context.content.join("\n\n")}`;
|
|
|
5219
5236
|
});
|
|
5220
5237
|
socket.on("message", (data) => {
|
|
5221
5238
|
try {
|
|
5222
|
-
const message = JSON.parse(
|
|
5239
|
+
const message = JSON.parse(
|
|
5240
|
+
data.toString()
|
|
5241
|
+
);
|
|
5223
5242
|
handleBrowserMessage(socket, message);
|
|
5224
5243
|
} catch {
|
|
5225
5244
|
}
|
|
@@ -5264,7 +5283,10 @@ ${context.content.join("\n\n")}`;
|
|
|
5264
5283
|
httpServer?.close();
|
|
5265
5284
|
};
|
|
5266
5285
|
const registerHandler = (handler) => {
|
|
5267
|
-
registeredHandlers.set(handler.agentId, {
|
|
5286
|
+
registeredHandlers.set(handler.agentId, {
|
|
5287
|
+
agentId: handler.agentId,
|
|
5288
|
+
handler
|
|
5289
|
+
});
|
|
5268
5290
|
broadcastHandlerList();
|
|
5269
5291
|
};
|
|
5270
5292
|
const unregisterHandler = (agentId) => {
|
|
@@ -7825,7 +7847,7 @@ async function fkill(inputs, options = {}) {
|
|
|
7825
7847
|
}
|
|
7826
7848
|
}
|
|
7827
7849
|
var sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
7828
|
-
var VERSION = "0.1.0
|
|
7850
|
+
var VERSION = "0.1.0";
|
|
7829
7851
|
var checkIfRelayServerIsRunning = async (port, token) => {
|
|
7830
7852
|
try {
|
|
7831
7853
|
const healthUrl = token ? `http://localhost:${port}/health?${RELAY_TOKEN_PARAM}=${encodeURIComponent(token)}` : `http://localhost:${port}/health`;
|
|
@@ -7843,7 +7865,10 @@ var connectRelay = async (options) => {
|
|
|
7843
7865
|
const { handler, token } = options;
|
|
7844
7866
|
let relayServer = null;
|
|
7845
7867
|
let isRelayHost = false;
|
|
7846
|
-
const isRelayServerRunning = await checkIfRelayServerIsRunning(
|
|
7868
|
+
const isRelayServerRunning = await checkIfRelayServerIsRunning(
|
|
7869
|
+
relayPort,
|
|
7870
|
+
token
|
|
7871
|
+
);
|
|
7847
7872
|
if (isRelayServerRunning) {
|
|
7848
7873
|
relayServer = await connectToExistingRelay(relayPort, handler, token);
|
|
7849
7874
|
} else {
|
package/dist/client.cjs
CHANGED
|
@@ -210,7 +210,7 @@ var createRelayAgentProvider = (options) => {
|
|
|
210
210
|
rejectNextMessage = null;
|
|
211
211
|
}
|
|
212
212
|
};
|
|
213
|
-
signal.addEventListener("abort", handleAbort);
|
|
213
|
+
signal.addEventListener("abort", handleAbort, { once: true });
|
|
214
214
|
const handleConnectionChange = (connected) => {
|
|
215
215
|
if (!connected && !isDone) {
|
|
216
216
|
errorMessage = "Relay connection lost";
|
|
@@ -260,7 +260,10 @@ var createRelayAgentProvider = (options) => {
|
|
|
260
260
|
signal.removeEventListener("abort", handleAbort);
|
|
261
261
|
throw new Error("Relay connection is not open");
|
|
262
262
|
}
|
|
263
|
-
const didSendRequest = relayClient.sendAgentRequest(
|
|
263
|
+
const didSendRequest = relayClient.sendAgentRequest(
|
|
264
|
+
agentId,
|
|
265
|
+
contextWithSession
|
|
266
|
+
);
|
|
264
267
|
if (!didSendRequest) {
|
|
265
268
|
unsubscribeConnection();
|
|
266
269
|
unsubscribeMessage();
|
|
@@ -318,12 +321,16 @@ var createRelayAgentProvider = (options) => {
|
|
|
318
321
|
reject(new Error(message.content ?? "Operation failed"));
|
|
319
322
|
}
|
|
320
323
|
});
|
|
321
|
-
const unsubscribeConnection = relayClient.onConnectionChange(
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
324
|
+
const unsubscribeConnection = relayClient.onConnectionChange(
|
|
325
|
+
(connected) => {
|
|
326
|
+
if (!connected) {
|
|
327
|
+
cleanup();
|
|
328
|
+
reject(
|
|
329
|
+
new Error("Connection lost while waiting for operation response")
|
|
330
|
+
);
|
|
331
|
+
}
|
|
325
332
|
}
|
|
326
|
-
|
|
333
|
+
);
|
|
327
334
|
});
|
|
328
335
|
};
|
|
329
336
|
const undo = async () => {
|
package/dist/client.global.js
CHANGED
|
@@ -1,2 +1,449 @@
|
|
|
1
|
-
var ReactGrabAmp
|
|
2
|
-
|
|
1
|
+
var ReactGrabAmp = (function (exports) {
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
// ../relay/dist/client.js
|
|
5
|
+
var DEFAULT_RELAY_PORT = 4722;
|
|
6
|
+
var DEFAULT_RECONNECT_INTERVAL_MS = 3e3;
|
|
7
|
+
var RELAY_TOKEN_PARAM = "token";
|
|
8
|
+
var createRelayClient = (options = {}) => {
|
|
9
|
+
const serverUrl = options.serverUrl ?? `ws://localhost:${DEFAULT_RELAY_PORT}`;
|
|
10
|
+
const autoReconnect = options.autoReconnect ?? true;
|
|
11
|
+
const reconnectIntervalMs = options.reconnectIntervalMs ?? DEFAULT_RECONNECT_INTERVAL_MS;
|
|
12
|
+
const token = options.token;
|
|
13
|
+
let webSocketConnection = null;
|
|
14
|
+
let isConnectedState = false;
|
|
15
|
+
let availableHandlers = [];
|
|
16
|
+
let reconnectTimeoutId = null;
|
|
17
|
+
let pendingConnectionPromise = null;
|
|
18
|
+
let pendingConnectionReject = null;
|
|
19
|
+
let isIntentionalDisconnect = false;
|
|
20
|
+
const messageCallbacks = /* @__PURE__ */ new Set();
|
|
21
|
+
const handlersChangeCallbacks = /* @__PURE__ */ new Set();
|
|
22
|
+
const connectionChangeCallbacks = /* @__PURE__ */ new Set();
|
|
23
|
+
const scheduleReconnect = () => {
|
|
24
|
+
if (!autoReconnect || reconnectTimeoutId || isIntentionalDisconnect) return;
|
|
25
|
+
reconnectTimeoutId = setTimeout(() => {
|
|
26
|
+
reconnectTimeoutId = null;
|
|
27
|
+
connect().catch(() => {
|
|
28
|
+
});
|
|
29
|
+
}, reconnectIntervalMs);
|
|
30
|
+
};
|
|
31
|
+
const handleMessage = (event) => {
|
|
32
|
+
try {
|
|
33
|
+
const message = JSON.parse(event.data);
|
|
34
|
+
if (message.type === "handlers" && message.handlers) {
|
|
35
|
+
availableHandlers = message.handlers;
|
|
36
|
+
for (const callback of handlersChangeCallbacks) {
|
|
37
|
+
callback(availableHandlers);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
for (const callback of messageCallbacks) {
|
|
41
|
+
callback(message);
|
|
42
|
+
}
|
|
43
|
+
} catch {
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
const connect = () => {
|
|
47
|
+
if (webSocketConnection?.readyState === WebSocket.OPEN) {
|
|
48
|
+
return Promise.resolve();
|
|
49
|
+
}
|
|
50
|
+
if (pendingConnectionPromise) {
|
|
51
|
+
return pendingConnectionPromise;
|
|
52
|
+
}
|
|
53
|
+
isIntentionalDisconnect = false;
|
|
54
|
+
pendingConnectionPromise = new Promise((resolve, reject) => {
|
|
55
|
+
pendingConnectionReject = reject;
|
|
56
|
+
const connectionUrl = token ? `${serverUrl}?${RELAY_TOKEN_PARAM}=${encodeURIComponent(token)}` : serverUrl;
|
|
57
|
+
webSocketConnection = new WebSocket(connectionUrl);
|
|
58
|
+
webSocketConnection.onopen = () => {
|
|
59
|
+
pendingConnectionPromise = null;
|
|
60
|
+
pendingConnectionReject = null;
|
|
61
|
+
isConnectedState = true;
|
|
62
|
+
for (const callback of connectionChangeCallbacks) {
|
|
63
|
+
callback(true);
|
|
64
|
+
}
|
|
65
|
+
resolve();
|
|
66
|
+
};
|
|
67
|
+
webSocketConnection.onmessage = handleMessage;
|
|
68
|
+
webSocketConnection.onclose = () => {
|
|
69
|
+
if (pendingConnectionReject) {
|
|
70
|
+
pendingConnectionReject(new Error("WebSocket connection closed"));
|
|
71
|
+
pendingConnectionReject = null;
|
|
72
|
+
}
|
|
73
|
+
pendingConnectionPromise = null;
|
|
74
|
+
isConnectedState = false;
|
|
75
|
+
availableHandlers = [];
|
|
76
|
+
for (const callback of handlersChangeCallbacks) {
|
|
77
|
+
callback(availableHandlers);
|
|
78
|
+
}
|
|
79
|
+
for (const callback of connectionChangeCallbacks) {
|
|
80
|
+
callback(false);
|
|
81
|
+
}
|
|
82
|
+
scheduleReconnect();
|
|
83
|
+
};
|
|
84
|
+
webSocketConnection.onerror = () => {
|
|
85
|
+
pendingConnectionPromise = null;
|
|
86
|
+
pendingConnectionReject = null;
|
|
87
|
+
isConnectedState = false;
|
|
88
|
+
reject(new Error("WebSocket connection failed"));
|
|
89
|
+
};
|
|
90
|
+
});
|
|
91
|
+
return pendingConnectionPromise;
|
|
92
|
+
};
|
|
93
|
+
const disconnect = () => {
|
|
94
|
+
isIntentionalDisconnect = true;
|
|
95
|
+
if (reconnectTimeoutId) {
|
|
96
|
+
clearTimeout(reconnectTimeoutId);
|
|
97
|
+
reconnectTimeoutId = null;
|
|
98
|
+
}
|
|
99
|
+
if (pendingConnectionReject) {
|
|
100
|
+
pendingConnectionReject(new Error("Connection aborted"));
|
|
101
|
+
pendingConnectionReject = null;
|
|
102
|
+
}
|
|
103
|
+
pendingConnectionPromise = null;
|
|
104
|
+
webSocketConnection?.close();
|
|
105
|
+
webSocketConnection = null;
|
|
106
|
+
isConnectedState = false;
|
|
107
|
+
availableHandlers = [];
|
|
108
|
+
};
|
|
109
|
+
const isConnected = () => isConnectedState;
|
|
110
|
+
const sendMessage = (message) => {
|
|
111
|
+
if (webSocketConnection?.readyState === WebSocket.OPEN) {
|
|
112
|
+
webSocketConnection.send(JSON.stringify(message));
|
|
113
|
+
return true;
|
|
114
|
+
}
|
|
115
|
+
return false;
|
|
116
|
+
};
|
|
117
|
+
const sendAgentRequest = (agentId, context) => {
|
|
118
|
+
return sendMessage({
|
|
119
|
+
type: "agent-request",
|
|
120
|
+
agentId,
|
|
121
|
+
sessionId: context.sessionId,
|
|
122
|
+
context
|
|
123
|
+
});
|
|
124
|
+
};
|
|
125
|
+
const abortAgent = (agentId, sessionId) => {
|
|
126
|
+
sendMessage({
|
|
127
|
+
type: "agent-abort",
|
|
128
|
+
agentId,
|
|
129
|
+
sessionId
|
|
130
|
+
});
|
|
131
|
+
};
|
|
132
|
+
const undoAgent = (agentId, sessionId) => {
|
|
133
|
+
return sendMessage({
|
|
134
|
+
type: "agent-undo",
|
|
135
|
+
agentId,
|
|
136
|
+
sessionId
|
|
137
|
+
});
|
|
138
|
+
};
|
|
139
|
+
const redoAgent = (agentId, sessionId) => {
|
|
140
|
+
return sendMessage({
|
|
141
|
+
type: "agent-redo",
|
|
142
|
+
agentId,
|
|
143
|
+
sessionId
|
|
144
|
+
});
|
|
145
|
+
};
|
|
146
|
+
const onMessage = (callback) => {
|
|
147
|
+
messageCallbacks.add(callback);
|
|
148
|
+
return () => messageCallbacks.delete(callback);
|
|
149
|
+
};
|
|
150
|
+
const onHandlersChange = (callback) => {
|
|
151
|
+
handlersChangeCallbacks.add(callback);
|
|
152
|
+
return () => handlersChangeCallbacks.delete(callback);
|
|
153
|
+
};
|
|
154
|
+
const onConnectionChange = (callback) => {
|
|
155
|
+
connectionChangeCallbacks.add(callback);
|
|
156
|
+
queueMicrotask(() => {
|
|
157
|
+
if (connectionChangeCallbacks.has(callback)) {
|
|
158
|
+
callback(isConnectedState);
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
return () => connectionChangeCallbacks.delete(callback);
|
|
162
|
+
};
|
|
163
|
+
const getAvailableHandlers = () => availableHandlers;
|
|
164
|
+
return {
|
|
165
|
+
connect,
|
|
166
|
+
disconnect,
|
|
167
|
+
isConnected,
|
|
168
|
+
sendAgentRequest,
|
|
169
|
+
abortAgent,
|
|
170
|
+
undoAgent,
|
|
171
|
+
redoAgent,
|
|
172
|
+
onMessage,
|
|
173
|
+
onHandlersChange,
|
|
174
|
+
onConnectionChange,
|
|
175
|
+
getAvailableHandlers
|
|
176
|
+
};
|
|
177
|
+
};
|
|
178
|
+
var createRelayAgentProvider = (options) => {
|
|
179
|
+
const { relayClient, agentId } = options;
|
|
180
|
+
const checkConnection = async () => {
|
|
181
|
+
if (!relayClient.isConnected()) {
|
|
182
|
+
try {
|
|
183
|
+
await relayClient.connect();
|
|
184
|
+
} catch {
|
|
185
|
+
return false;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
return relayClient.getAvailableHandlers().includes(agentId);
|
|
189
|
+
};
|
|
190
|
+
const send = async function* (context, signal) {
|
|
191
|
+
if (signal.aborted) {
|
|
192
|
+
throw new DOMException("Aborted", "AbortError");
|
|
193
|
+
}
|
|
194
|
+
yield "Connecting\u2026";
|
|
195
|
+
const sessionId = context.sessionId ?? `session-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
196
|
+
const contextWithSession = {
|
|
197
|
+
...context,
|
|
198
|
+
sessionId
|
|
199
|
+
};
|
|
200
|
+
const messageQueue = [];
|
|
201
|
+
let resolveNextMessage = null;
|
|
202
|
+
let rejectNextMessage = null;
|
|
203
|
+
let isDone = false;
|
|
204
|
+
let errorMessage = null;
|
|
205
|
+
const handleAbort = () => {
|
|
206
|
+
relayClient.abortAgent(agentId, sessionId);
|
|
207
|
+
isDone = true;
|
|
208
|
+
if (resolveNextMessage) {
|
|
209
|
+
resolveNextMessage({ value: void 0, done: true });
|
|
210
|
+
resolveNextMessage = null;
|
|
211
|
+
rejectNextMessage = null;
|
|
212
|
+
}
|
|
213
|
+
};
|
|
214
|
+
signal.addEventListener("abort", handleAbort, { once: true });
|
|
215
|
+
const handleConnectionChange = (connected) => {
|
|
216
|
+
if (!connected && !isDone) {
|
|
217
|
+
errorMessage = "Relay connection lost";
|
|
218
|
+
isDone = true;
|
|
219
|
+
if (rejectNextMessage) {
|
|
220
|
+
rejectNextMessage(new Error(errorMessage));
|
|
221
|
+
resolveNextMessage = null;
|
|
222
|
+
rejectNextMessage = null;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
};
|
|
226
|
+
const unsubscribeConnection = relayClient.onConnectionChange(
|
|
227
|
+
handleConnectionChange
|
|
228
|
+
);
|
|
229
|
+
const unsubscribeMessage = relayClient.onMessage((message) => {
|
|
230
|
+
if (message.sessionId !== sessionId) return;
|
|
231
|
+
if (message.type === "agent-status" && message.content) {
|
|
232
|
+
messageQueue.push(message.content);
|
|
233
|
+
if (resolveNextMessage) {
|
|
234
|
+
const nextMessage = messageQueue.shift();
|
|
235
|
+
if (nextMessage !== void 0) {
|
|
236
|
+
resolveNextMessage({ value: nextMessage, done: false });
|
|
237
|
+
resolveNextMessage = null;
|
|
238
|
+
rejectNextMessage = null;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
} else if (message.type === "agent-done") {
|
|
242
|
+
isDone = true;
|
|
243
|
+
if (resolveNextMessage) {
|
|
244
|
+
resolveNextMessage({ value: void 0, done: true });
|
|
245
|
+
resolveNextMessage = null;
|
|
246
|
+
rejectNextMessage = null;
|
|
247
|
+
}
|
|
248
|
+
} else if (message.type === "agent-error") {
|
|
249
|
+
errorMessage = message.content ?? "Unknown error";
|
|
250
|
+
isDone = true;
|
|
251
|
+
if (rejectNextMessage) {
|
|
252
|
+
rejectNextMessage(new Error(errorMessage));
|
|
253
|
+
resolveNextMessage = null;
|
|
254
|
+
rejectNextMessage = null;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
});
|
|
258
|
+
if (!relayClient.isConnected()) {
|
|
259
|
+
unsubscribeConnection();
|
|
260
|
+
unsubscribeMessage();
|
|
261
|
+
signal.removeEventListener("abort", handleAbort);
|
|
262
|
+
throw new Error("Relay connection is not open");
|
|
263
|
+
}
|
|
264
|
+
const didSendRequest = relayClient.sendAgentRequest(
|
|
265
|
+
agentId,
|
|
266
|
+
contextWithSession
|
|
267
|
+
);
|
|
268
|
+
if (!didSendRequest) {
|
|
269
|
+
unsubscribeConnection();
|
|
270
|
+
unsubscribeMessage();
|
|
271
|
+
signal.removeEventListener("abort", handleAbort);
|
|
272
|
+
throw new Error("Failed to send agent request: connection not open");
|
|
273
|
+
}
|
|
274
|
+
try {
|
|
275
|
+
while (true) {
|
|
276
|
+
if (messageQueue.length > 0) {
|
|
277
|
+
const next = messageQueue.shift();
|
|
278
|
+
if (next !== void 0) {
|
|
279
|
+
yield next;
|
|
280
|
+
}
|
|
281
|
+
continue;
|
|
282
|
+
}
|
|
283
|
+
if (isDone || signal.aborted) {
|
|
284
|
+
break;
|
|
285
|
+
}
|
|
286
|
+
const result = await new Promise(
|
|
287
|
+
(resolve, reject) => {
|
|
288
|
+
resolveNextMessage = resolve;
|
|
289
|
+
rejectNextMessage = reject;
|
|
290
|
+
}
|
|
291
|
+
);
|
|
292
|
+
if (result.done) break;
|
|
293
|
+
yield result.value;
|
|
294
|
+
}
|
|
295
|
+
if (errorMessage) {
|
|
296
|
+
throw new Error(errorMessage);
|
|
297
|
+
}
|
|
298
|
+
} finally {
|
|
299
|
+
signal.removeEventListener("abort", handleAbort);
|
|
300
|
+
unsubscribeConnection();
|
|
301
|
+
unsubscribeMessage();
|
|
302
|
+
}
|
|
303
|
+
};
|
|
304
|
+
const abort = async (sessionId) => {
|
|
305
|
+
relayClient.abortAgent(agentId, sessionId);
|
|
306
|
+
};
|
|
307
|
+
const waitForOperationResponse = (sessionId) => {
|
|
308
|
+
return new Promise((resolve, reject) => {
|
|
309
|
+
let didCleanup = false;
|
|
310
|
+
const cleanup = () => {
|
|
311
|
+
if (didCleanup) return;
|
|
312
|
+
didCleanup = true;
|
|
313
|
+
unsubscribeMessage();
|
|
314
|
+
unsubscribeConnection();
|
|
315
|
+
};
|
|
316
|
+
const unsubscribeMessage = relayClient.onMessage((message) => {
|
|
317
|
+
if (message.sessionId !== sessionId) return;
|
|
318
|
+
cleanup();
|
|
319
|
+
if (message.type === "agent-done") {
|
|
320
|
+
resolve();
|
|
321
|
+
} else if (message.type === "agent-error") {
|
|
322
|
+
reject(new Error(message.content ?? "Operation failed"));
|
|
323
|
+
}
|
|
324
|
+
});
|
|
325
|
+
const unsubscribeConnection = relayClient.onConnectionChange(
|
|
326
|
+
(connected) => {
|
|
327
|
+
if (!connected) {
|
|
328
|
+
cleanup();
|
|
329
|
+
reject(
|
|
330
|
+
new Error("Connection lost while waiting for operation response")
|
|
331
|
+
);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
);
|
|
335
|
+
});
|
|
336
|
+
};
|
|
337
|
+
const undo = async () => {
|
|
338
|
+
const sessionId = `undo-${agentId}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
339
|
+
const didSend = relayClient.undoAgent(agentId, sessionId);
|
|
340
|
+
if (!didSend) {
|
|
341
|
+
throw new Error("Failed to send undo request: connection not open");
|
|
342
|
+
}
|
|
343
|
+
return waitForOperationResponse(sessionId);
|
|
344
|
+
};
|
|
345
|
+
const redo = async () => {
|
|
346
|
+
const sessionId = `redo-${agentId}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
347
|
+
const didSend = relayClient.redoAgent(agentId, sessionId);
|
|
348
|
+
if (!didSend) {
|
|
349
|
+
throw new Error("Failed to send redo request: connection not open");
|
|
350
|
+
}
|
|
351
|
+
return waitForOperationResponse(sessionId);
|
|
352
|
+
};
|
|
353
|
+
return {
|
|
354
|
+
send,
|
|
355
|
+
abort,
|
|
356
|
+
undo,
|
|
357
|
+
redo,
|
|
358
|
+
checkConnection,
|
|
359
|
+
supportsResume: true,
|
|
360
|
+
supportsFollowUp: true
|
|
361
|
+
};
|
|
362
|
+
};
|
|
363
|
+
var defaultRelayClient = null;
|
|
364
|
+
var getDefaultRelayClient = () => {
|
|
365
|
+
if (typeof window === "undefined") {
|
|
366
|
+
return null;
|
|
367
|
+
}
|
|
368
|
+
if (window.__REACT_GRAB_RELAY__) {
|
|
369
|
+
defaultRelayClient = window.__REACT_GRAB_RELAY__;
|
|
370
|
+
return defaultRelayClient;
|
|
371
|
+
}
|
|
372
|
+
if (!defaultRelayClient) {
|
|
373
|
+
defaultRelayClient = createRelayClient();
|
|
374
|
+
window.__REACT_GRAB_RELAY__ = defaultRelayClient;
|
|
375
|
+
}
|
|
376
|
+
return defaultRelayClient;
|
|
377
|
+
};
|
|
378
|
+
|
|
379
|
+
// src/client.ts
|
|
380
|
+
var AGENT_ID = "amp";
|
|
381
|
+
var isReactGrabApi = (value) => typeof value === "object" && value !== null && "registerPlugin" in value;
|
|
382
|
+
var createAmpAgentProvider = (providerOptions = {}) => {
|
|
383
|
+
const relayClient = providerOptions.relayClient ?? getDefaultRelayClient();
|
|
384
|
+
if (!relayClient) {
|
|
385
|
+
throw new Error("RelayClient is required in browser environments");
|
|
386
|
+
}
|
|
387
|
+
return createRelayAgentProvider({
|
|
388
|
+
relayClient,
|
|
389
|
+
agentId: AGENT_ID
|
|
390
|
+
});
|
|
391
|
+
};
|
|
392
|
+
var attachAgent = async () => {
|
|
393
|
+
if (typeof window === "undefined") return;
|
|
394
|
+
const relayClient = getDefaultRelayClient();
|
|
395
|
+
if (!relayClient) return;
|
|
396
|
+
try {
|
|
397
|
+
await relayClient.connect();
|
|
398
|
+
} catch {
|
|
399
|
+
return;
|
|
400
|
+
}
|
|
401
|
+
const provider = createRelayAgentProvider({
|
|
402
|
+
relayClient,
|
|
403
|
+
agentId: AGENT_ID
|
|
404
|
+
});
|
|
405
|
+
const attach = (api) => {
|
|
406
|
+
const agent = { provider, storage: sessionStorage };
|
|
407
|
+
const plugin = {
|
|
408
|
+
name: "amp-agent",
|
|
409
|
+
actions: [
|
|
410
|
+
{
|
|
411
|
+
id: "edit-with-amp",
|
|
412
|
+
label: "Edit with Amp",
|
|
413
|
+
shortcut: "Enter",
|
|
414
|
+
onAction: (actionContext) => {
|
|
415
|
+
actionContext.enterPromptMode?.(agent);
|
|
416
|
+
},
|
|
417
|
+
agent
|
|
418
|
+
}
|
|
419
|
+
]
|
|
420
|
+
};
|
|
421
|
+
api.registerPlugin(plugin);
|
|
422
|
+
};
|
|
423
|
+
const existingApi = window.__REACT_GRAB__;
|
|
424
|
+
if (isReactGrabApi(existingApi)) {
|
|
425
|
+
attach(existingApi);
|
|
426
|
+
return;
|
|
427
|
+
}
|
|
428
|
+
window.addEventListener(
|
|
429
|
+
"react-grab:init",
|
|
430
|
+
(event) => {
|
|
431
|
+
if (!(event instanceof CustomEvent)) return;
|
|
432
|
+
if (!isReactGrabApi(event.detail)) return;
|
|
433
|
+
attach(event.detail);
|
|
434
|
+
},
|
|
435
|
+
{ once: true }
|
|
436
|
+
);
|
|
437
|
+
const apiAfterListener = window.__REACT_GRAB__;
|
|
438
|
+
if (isReactGrabApi(apiAfterListener)) {
|
|
439
|
+
attach(apiAfterListener);
|
|
440
|
+
}
|
|
441
|
+
};
|
|
442
|
+
attachAgent();
|
|
443
|
+
|
|
444
|
+
exports.attachAgent = attachAgent;
|
|
445
|
+
exports.createAmpAgentProvider = createAmpAgentProvider;
|
|
446
|
+
|
|
447
|
+
return exports;
|
|
448
|
+
|
|
449
|
+
})({});
|
package/dist/client.js
CHANGED
|
@@ -208,7 +208,7 @@ var createRelayAgentProvider = (options) => {
|
|
|
208
208
|
rejectNextMessage = null;
|
|
209
209
|
}
|
|
210
210
|
};
|
|
211
|
-
signal.addEventListener("abort", handleAbort);
|
|
211
|
+
signal.addEventListener("abort", handleAbort, { once: true });
|
|
212
212
|
const handleConnectionChange = (connected) => {
|
|
213
213
|
if (!connected && !isDone) {
|
|
214
214
|
errorMessage = "Relay connection lost";
|
|
@@ -258,7 +258,10 @@ var createRelayAgentProvider = (options) => {
|
|
|
258
258
|
signal.removeEventListener("abort", handleAbort);
|
|
259
259
|
throw new Error("Relay connection is not open");
|
|
260
260
|
}
|
|
261
|
-
const didSendRequest = relayClient.sendAgentRequest(
|
|
261
|
+
const didSendRequest = relayClient.sendAgentRequest(
|
|
262
|
+
agentId,
|
|
263
|
+
contextWithSession
|
|
264
|
+
);
|
|
262
265
|
if (!didSendRequest) {
|
|
263
266
|
unsubscribeConnection();
|
|
264
267
|
unsubscribeMessage();
|
|
@@ -316,12 +319,16 @@ var createRelayAgentProvider = (options) => {
|
|
|
316
319
|
reject(new Error(message.content ?? "Operation failed"));
|
|
317
320
|
}
|
|
318
321
|
});
|
|
319
|
-
const unsubscribeConnection = relayClient.onConnectionChange(
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
322
|
+
const unsubscribeConnection = relayClient.onConnectionChange(
|
|
323
|
+
(connected) => {
|
|
324
|
+
if (!connected) {
|
|
325
|
+
cleanup();
|
|
326
|
+
reject(
|
|
327
|
+
new Error("Connection lost while waiting for operation response")
|
|
328
|
+
);
|
|
329
|
+
}
|
|
323
330
|
}
|
|
324
|
-
|
|
331
|
+
);
|
|
325
332
|
});
|
|
326
333
|
};
|
|
327
334
|
const undo = async () => {
|
package/package.json
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@react-grab/amp",
|
|
3
|
-
"version": "0.1.0
|
|
4
|
-
"type": "module",
|
|
3
|
+
"version": "0.1.0",
|
|
5
4
|
"bin": {
|
|
6
5
|
"react-grab-amp": "./dist/cli.cjs"
|
|
7
6
|
},
|
|
7
|
+
"files": [
|
|
8
|
+
"dist"
|
|
9
|
+
],
|
|
10
|
+
"type": "module",
|
|
11
|
+
"browser": "dist/client.global.js",
|
|
8
12
|
"exports": {
|
|
9
13
|
"./client": {
|
|
10
14
|
"types": "./dist/client.d.ts",
|
|
@@ -19,20 +23,16 @@
|
|
|
19
23
|
"./dist/*": "./dist/*.js",
|
|
20
24
|
"./dist/*.js": "./dist/*.js"
|
|
21
25
|
},
|
|
22
|
-
"browser": "dist/client.global.js",
|
|
23
|
-
"files": [
|
|
24
|
-
"dist"
|
|
25
|
-
],
|
|
26
|
-
"devDependencies": {
|
|
27
|
-
"@types/node": "^22.10.7",
|
|
28
|
-
"tsup": "^8.4.0",
|
|
29
|
-
"@react-grab/utils": "0.1.0-beta.8"
|
|
30
|
-
},
|
|
31
26
|
"dependencies": {
|
|
32
27
|
"@sourcegraph/amp": "^0.0.1767830505-ga62310",
|
|
33
28
|
"@sourcegraph/amp-sdk": "^0.1.0-20251210081226-g90e3892",
|
|
34
|
-
"
|
|
35
|
-
"react-grab": "0.1.0
|
|
29
|
+
"react-grab": "0.1.0",
|
|
30
|
+
"@react-grab/relay": "0.1.0"
|
|
31
|
+
},
|
|
32
|
+
"devDependencies": {
|
|
33
|
+
"@types/node": "^22.10.7",
|
|
34
|
+
"tsup": "^8.4.0",
|
|
35
|
+
"@react-grab/utils": "0.1.0"
|
|
36
36
|
},
|
|
37
37
|
"scripts": {
|
|
38
38
|
"dev": "tsup --watch",
|