@buygent/cli 0.3.9 → 0.4.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.js +188 -178
- package/dist/extension/content/amazon.js +280 -0
- package/dist/extension/content/coupang.js +30 -13
- package/dist/extension/manifest.json +15 -3
- package/dist/native-host.js +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
(() => {
|
|
2
|
+
// extension/protocol.ts
|
|
3
|
+
var BUYGENT_PROTOCOL_VERSION = 1;
|
|
4
|
+
var BUYGENT_NATIVE_HOST_NAME = "com.buygent.host";
|
|
5
|
+
var NATIVE_HOST_SOCKET_FILENAME = `${BUYGENT_NATIVE_HOST_NAME}.sock`;
|
|
6
|
+
var createEnvelope = (type, payload, options) => ({
|
|
7
|
+
protocolVersion: BUYGENT_PROTOCOL_VERSION,
|
|
8
|
+
type,
|
|
9
|
+
messageId: options.messageId,
|
|
10
|
+
...options.requestId ? { requestId: options.requestId } : {},
|
|
11
|
+
sentAt: options.sentAt ?? new Date().toISOString(),
|
|
12
|
+
source: options.source,
|
|
13
|
+
payload
|
|
14
|
+
});
|
|
15
|
+
var createErrorEnvelope = (payload, options) => createEnvelope("error", payload, options);
|
|
16
|
+
var isRecord = (value) => Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
17
|
+
var decodeEnvelope = (raw, options = {}) => {
|
|
18
|
+
const fallback = {
|
|
19
|
+
source: options.source ?? "native-host",
|
|
20
|
+
messageId: options.messageId ?? `protocol_${Date.now()}`,
|
|
21
|
+
requestId: options.requestId,
|
|
22
|
+
sentAt: options.sentAt
|
|
23
|
+
};
|
|
24
|
+
if (!isRecord(raw)) {
|
|
25
|
+
return {
|
|
26
|
+
ok: false,
|
|
27
|
+
error: createErrorEnvelope({
|
|
28
|
+
code: "invalid_envelope",
|
|
29
|
+
message: "Expected a JSON object envelope."
|
|
30
|
+
}, fallback)
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
if (raw.protocolVersion !== BUYGENT_PROTOCOL_VERSION) {
|
|
34
|
+
return {
|
|
35
|
+
ok: false,
|
|
36
|
+
error: createErrorEnvelope({
|
|
37
|
+
code: "unsupported_protocol_version",
|
|
38
|
+
message: `Unsupported protocolVersion: ${String(raw.protocolVersion ?? "missing")}`,
|
|
39
|
+
details: {
|
|
40
|
+
supportedProtocolVersion: BUYGENT_PROTOCOL_VERSION
|
|
41
|
+
}
|
|
42
|
+
}, fallback)
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
if (typeof raw.type !== "string" || typeof raw.messageId !== "string" || typeof raw.sentAt !== "string" || typeof raw.source !== "string") {
|
|
46
|
+
return {
|
|
47
|
+
ok: false,
|
|
48
|
+
error: createErrorEnvelope({
|
|
49
|
+
code: "invalid_envelope",
|
|
50
|
+
message: "Envelope must include type, messageId, sentAt, and source fields."
|
|
51
|
+
}, fallback)
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
return {
|
|
55
|
+
ok: true,
|
|
56
|
+
envelope: raw
|
|
57
|
+
};
|
|
58
|
+
};
|
|
59
|
+
var TERMINAL_ORDER_STATES = new Set(["aborted", "completed_dry_run"]);
|
|
60
|
+
|
|
61
|
+
// extension/amazon-selector-config.ts
|
|
62
|
+
var BUNDLED_AMAZON_SELECTOR_CONFIG = {
|
|
63
|
+
version: "amazon.v1",
|
|
64
|
+
platform: "amazon",
|
|
65
|
+
generatedAt: "2026-05-08T00:00:00.000Z",
|
|
66
|
+
selectors: {
|
|
67
|
+
loginIndicators: [
|
|
68
|
+
"#nav-link-accountList[data-nav-ref='nav_youraccount_btn']",
|
|
69
|
+
"#nav-item-signout",
|
|
70
|
+
"span.nav-line-1:not(:empty)"
|
|
71
|
+
],
|
|
72
|
+
loggedOutIndicators: [
|
|
73
|
+
"#nav-link-accountList span:first-child",
|
|
74
|
+
"a[href*='signin']"
|
|
75
|
+
],
|
|
76
|
+
productTitle: [
|
|
77
|
+
"#productTitle",
|
|
78
|
+
"#title span",
|
|
79
|
+
"h1.product-title-word-break"
|
|
80
|
+
],
|
|
81
|
+
productPrice: [
|
|
82
|
+
".a-price .a-offscreen",
|
|
83
|
+
"#priceblock_ourprice",
|
|
84
|
+
"#priceblock_dealprice",
|
|
85
|
+
"span.a-price-whole",
|
|
86
|
+
"#corePrice_feature_div .a-offscreen"
|
|
87
|
+
],
|
|
88
|
+
addToCartButton: [
|
|
89
|
+
"#add-to-cart-button",
|
|
90
|
+
"#add-to-cart-button-ubb",
|
|
91
|
+
"input[name='submit.add-to-cart']",
|
|
92
|
+
"#addToCart .a-button-text",
|
|
93
|
+
"span.a-button-text:has-text(Add to Cart)",
|
|
94
|
+
"#addToCart input[type='submit']"
|
|
95
|
+
],
|
|
96
|
+
buyNowButton: [
|
|
97
|
+
"#buy-now-button",
|
|
98
|
+
"#submitOrderButtonId",
|
|
99
|
+
"#buy-now-button .a-button-text"
|
|
100
|
+
],
|
|
101
|
+
optionSelectors: [
|
|
102
|
+
"#native_dropdown_selected_size_name",
|
|
103
|
+
"#native_dropdown_selected_color_name",
|
|
104
|
+
"#variation_size_name select",
|
|
105
|
+
"#variation_color_name ul li",
|
|
106
|
+
".a-dropdown-container select"
|
|
107
|
+
],
|
|
108
|
+
cartItems: [
|
|
109
|
+
".sc-list-item",
|
|
110
|
+
"div[data-item-id]",
|
|
111
|
+
".sc-list-body .sc-action-links"
|
|
112
|
+
],
|
|
113
|
+
cartTotal: [
|
|
114
|
+
"#sc-subtotal-amount-activecart",
|
|
115
|
+
"#sc-subtotal-label-activecart + .a-text-bold"
|
|
116
|
+
],
|
|
117
|
+
proceedToCheckout: [
|
|
118
|
+
"#sc-buy-box-ptc-button",
|
|
119
|
+
"input[name='proceedToRetailCheckout']",
|
|
120
|
+
"#hlb-ptc-btn-native"
|
|
121
|
+
],
|
|
122
|
+
placeOrder: [
|
|
123
|
+
"#submitOrderButtonId",
|
|
124
|
+
"#placeYourOrder input",
|
|
125
|
+
"#bottomSubmitOrderButtonId"
|
|
126
|
+
],
|
|
127
|
+
orderConfirmation: [
|
|
128
|
+
"#thank-you-page",
|
|
129
|
+
".a-alert-heading",
|
|
130
|
+
"#confirmationPage",
|
|
131
|
+
"h4.a-alert-heading"
|
|
132
|
+
],
|
|
133
|
+
searchInput: [
|
|
134
|
+
"#twotabsearchtextbox",
|
|
135
|
+
"#nav-search-keywords"
|
|
136
|
+
],
|
|
137
|
+
searchButton: [
|
|
138
|
+
"#nav-search-submit-button",
|
|
139
|
+
"input[type='submit'][value='Go']"
|
|
140
|
+
],
|
|
141
|
+
searchResults: [
|
|
142
|
+
"div[data-component-type='s-search-result']",
|
|
143
|
+
".s-result-item[data-asin]"
|
|
144
|
+
]
|
|
145
|
+
}
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
// extension/content/amazon-probe.ts
|
|
149
|
+
var detectPageType = (url) => {
|
|
150
|
+
if (/\/s[?/]/.test(url) || /\/s\?k=/.test(url))
|
|
151
|
+
return "search";
|
|
152
|
+
if (/\/dp\/|\/gp\/product\//.test(url))
|
|
153
|
+
return "product";
|
|
154
|
+
if (/\/cart|\/gp\/cart/.test(url))
|
|
155
|
+
return "cart";
|
|
156
|
+
if (/\/checkout|\/buy\//.test(url) || /\/gp\/buy/.test(url))
|
|
157
|
+
return "checkout";
|
|
158
|
+
if (/thankyou|order-confirmation|gp\/buy\/thankyou/.test(url))
|
|
159
|
+
return "orderConfirmation";
|
|
160
|
+
return "other";
|
|
161
|
+
};
|
|
162
|
+
var querySelector = (doc, selectors) => {
|
|
163
|
+
for (const sel of selectors) {
|
|
164
|
+
try {
|
|
165
|
+
const el = doc.querySelector(sel);
|
|
166
|
+
if (el)
|
|
167
|
+
return el;
|
|
168
|
+
} catch {}
|
|
169
|
+
}
|
|
170
|
+
return null;
|
|
171
|
+
};
|
|
172
|
+
var querySelectorAll = (doc, selectors) => {
|
|
173
|
+
const results = [];
|
|
174
|
+
for (const sel of selectors) {
|
|
175
|
+
try {
|
|
176
|
+
results.push(...Array.from(doc.querySelectorAll(sel)));
|
|
177
|
+
} catch {}
|
|
178
|
+
}
|
|
179
|
+
return results;
|
|
180
|
+
};
|
|
181
|
+
var getTextContent = (el) => el?.textContent?.trim() || null;
|
|
182
|
+
var buildAmazonProbe = (url, doc, config = BUNDLED_AMAZON_SELECTOR_CONFIG) => {
|
|
183
|
+
const { selectors } = config;
|
|
184
|
+
const pageType = detectPageType(url);
|
|
185
|
+
const hasLoginIndicator = selectors.loginIndicators.some((s) => {
|
|
186
|
+
try {
|
|
187
|
+
return !!doc.querySelector(s);
|
|
188
|
+
} catch {
|
|
189
|
+
return false;
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
const hasLoggedOutIndicator = selectors.loggedOutIndicators.some((s) => {
|
|
193
|
+
try {
|
|
194
|
+
return !!doc.querySelector(s);
|
|
195
|
+
} catch {
|
|
196
|
+
return false;
|
|
197
|
+
}
|
|
198
|
+
});
|
|
199
|
+
const isLoggedIn = hasLoginIndicator ? true : hasLoggedOutIndicator ? false : null;
|
|
200
|
+
let product = null;
|
|
201
|
+
if (pageType === "product") {
|
|
202
|
+
product = {
|
|
203
|
+
title: getTextContent(querySelector(doc, selectors.productTitle)),
|
|
204
|
+
price: getTextContent(querySelector(doc, selectors.productPrice)),
|
|
205
|
+
hasAddToCart: !!querySelector(doc, selectors.addToCartButton),
|
|
206
|
+
hasBuyNow: !!querySelector(doc, selectors.buyNowButton),
|
|
207
|
+
hasOptions: selectors.optionSelectors.some((s) => {
|
|
208
|
+
try {
|
|
209
|
+
return !!doc.querySelector(s);
|
|
210
|
+
} catch {
|
|
211
|
+
return false;
|
|
212
|
+
}
|
|
213
|
+
})
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
let cart = null;
|
|
217
|
+
if (pageType === "cart") {
|
|
218
|
+
const items = querySelectorAll(doc, selectors.cartItems);
|
|
219
|
+
cart = {
|
|
220
|
+
itemCount: items.length,
|
|
221
|
+
total: getTextContent(querySelector(doc, selectors.cartTotal)),
|
|
222
|
+
hasProceedToCheckout: !!querySelector(doc, selectors.proceedToCheckout)
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
let search = null;
|
|
226
|
+
if (pageType === "search") {
|
|
227
|
+
const searchInput = querySelector(doc, selectors.searchInput);
|
|
228
|
+
const results = querySelectorAll(doc, selectors.searchResults);
|
|
229
|
+
search = {
|
|
230
|
+
query: searchInput?.value || new URL(url).searchParams.get("k") || null,
|
|
231
|
+
resultCount: results.length
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
return { url, pageType, isLoggedIn, product, cart, search };
|
|
235
|
+
};
|
|
236
|
+
|
|
237
|
+
// extension/content/amazon.ts
|
|
238
|
+
var createRequestId = () => globalThis.crypto?.randomUUID?.() ?? `req_${Date.now()}_${Math.random().toString(16).slice(2)}`;
|
|
239
|
+
var sendBackgroundEnvelope = async (envelope) => {
|
|
240
|
+
try {
|
|
241
|
+
await chrome.runtime.sendMessage(envelope);
|
|
242
|
+
} catch {}
|
|
243
|
+
};
|
|
244
|
+
var handleProbe = (message) => {
|
|
245
|
+
try {
|
|
246
|
+
const probe = buildAmazonProbe(window.location.href, document, BUNDLED_AMAZON_SELECTOR_CONFIG);
|
|
247
|
+
return createEnvelope("amazon:probe-result", { probe }, {
|
|
248
|
+
source: "extension:content",
|
|
249
|
+
messageId: createRequestId(),
|
|
250
|
+
requestId: message.messageId
|
|
251
|
+
});
|
|
252
|
+
} catch (error) {
|
|
253
|
+
return createErrorEnvelope({
|
|
254
|
+
code: "internal_error",
|
|
255
|
+
message: error instanceof Error ? error.message : "Failed to inspect the Amazon page."
|
|
256
|
+
}, {
|
|
257
|
+
source: "extension:content",
|
|
258
|
+
messageId: createRequestId(),
|
|
259
|
+
requestId: message.messageId
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
};
|
|
263
|
+
chrome.runtime.onMessage.addListener((raw, _sender, sendResponse) => {
|
|
264
|
+
const decoded = decodeEnvelope(raw);
|
|
265
|
+
if (!decoded || !decoded.ok)
|
|
266
|
+
return;
|
|
267
|
+
const { envelope } = decoded;
|
|
268
|
+
switch (envelope.type) {
|
|
269
|
+
case "amazon:probe": {
|
|
270
|
+
const response = handleProbe(envelope);
|
|
271
|
+
sendBackgroundEnvelope(response);
|
|
272
|
+
sendResponse(response);
|
|
273
|
+
break;
|
|
274
|
+
}
|
|
275
|
+
default:
|
|
276
|
+
break;
|
|
277
|
+
}
|
|
278
|
+
});
|
|
279
|
+
sendBackgroundEnvelope(createEnvelope("content:ready", { platform: "amazon", url: window.location.href }, { source: "extension:content", messageId: createRequestId() }));
|
|
280
|
+
})();
|
|
@@ -671,19 +671,36 @@
|
|
|
671
671
|
const intervalMs = options?.intervalMs ?? 600;
|
|
672
672
|
const getCurrentUrl = options?.getCurrentUrl ?? (() => globalThis.location?.href ?? "");
|
|
673
673
|
const startUrl = getCurrentUrl();
|
|
674
|
+
let navigationDetected = false;
|
|
675
|
+
const onLeavingPage = () => {
|
|
676
|
+
navigationDetected = true;
|
|
677
|
+
};
|
|
678
|
+
const navigationEventTarget = typeof window !== "undefined" && typeof window.addEventListener === "function" ? window : undefined;
|
|
679
|
+
navigationEventTarget?.addEventListener("pagehide", onLeavingPage, { once: true });
|
|
680
|
+
navigationEventTarget?.addEventListener("beforeunload", onLeavingPage, { once: true });
|
|
674
681
|
const deadline = Date.now() + totalTimeoutMs;
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
682
|
+
let clicksDispatched = 0;
|
|
683
|
+
try {
|
|
684
|
+
while (Date.now() < deadline) {
|
|
685
|
+
try {
|
|
686
|
+
element.click();
|
|
687
|
+
clicksDispatched += 1;
|
|
688
|
+
} catch {}
|
|
689
|
+
await wait2(intervalMs);
|
|
690
|
+
if (navigationDetected) {
|
|
691
|
+
return { navigated: true, clicksDispatched };
|
|
692
|
+
}
|
|
693
|
+
const currentUrl = getCurrentUrl();
|
|
694
|
+
const navigated = options?.expectedUrlPattern ? options.expectedUrlPattern.test(currentUrl) : currentUrl !== startUrl;
|
|
695
|
+
if (navigated) {
|
|
696
|
+
return { navigated: true, clicksDispatched };
|
|
697
|
+
}
|
|
684
698
|
}
|
|
699
|
+
return { navigated: false, clicksDispatched };
|
|
700
|
+
} finally {
|
|
701
|
+
navigationEventTarget?.removeEventListener("pagehide", onLeavingPage);
|
|
702
|
+
navigationEventTarget?.removeEventListener("beforeunload", onLeavingPage);
|
|
685
703
|
}
|
|
686
|
-
return false;
|
|
687
704
|
};
|
|
688
705
|
var checkpointPatchFromProbe = (request, checkpoint, probe) => ({
|
|
689
706
|
productUrl: request.productUrl,
|
|
@@ -1016,14 +1033,14 @@
|
|
|
1016
1033
|
if (!found) {
|
|
1017
1034
|
throw new Error("Unable to find the Coupang cart order button.");
|
|
1018
1035
|
}
|
|
1019
|
-
const
|
|
1036
|
+
const result = await clickAndAwaitNavigation(found, {
|
|
1020
1037
|
totalTimeoutMs: 12000,
|
|
1021
1038
|
intervalMs: 600,
|
|
1022
1039
|
expectedUrlPattern: /checkout\.coupang\.com|\/cart\/checkout/,
|
|
1023
1040
|
getCurrentUrl: () => location.href
|
|
1024
1041
|
});
|
|
1025
|
-
if (!navigated) {
|
|
1026
|
-
throw new Error("
|
|
1042
|
+
if (!result.navigated && result.clicksDispatched === 0) {
|
|
1043
|
+
throw new Error("Unable to dispatch click on the Coupang cart order button.");
|
|
1027
1044
|
}
|
|
1028
1045
|
}
|
|
1029
1046
|
};
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"manifest_version": 3,
|
|
3
3
|
"name": "Buygent",
|
|
4
4
|
"version": "0.1.0",
|
|
5
|
-
"description": "Buygent BYOK bridge for
|
|
5
|
+
"description": "Buygent BYOK bridge for AI-assisted shopping on Coupang and Amazon.",
|
|
6
6
|
"key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAz9QWmSM8oHI1SIgpWOs2Qd+svxqlch1W0ctBFtbHK7oUw5y0RFfu5hmB1khciag0ii4jjvitdCMt2yj3Oug3Kc+NZ9wijP5oz+bwW8y+7u9hXjZu+eAZjHuclUvl+yBnL0Ny4altosfWA3x0Lih2S7ZCCrZR/Jx6Gk483XgZE9VBPz5Banu7hqF8qleWX0LvrJXwUp3RWFywWXdq1LswQLcQtx9niygpGMvGr1DKlJ8+iDw4Cn8XUCzp1+n74DBHAz6eKbl+5iOoFCLYxzOeEfs0ABXGlrL0ShF2mgwt/3+ucL2wTWe1atXOJHmmmhU3bK4anyFFUMzTsTA+Io96+wIDAQAB",
|
|
7
7
|
"permissions": [
|
|
8
8
|
"activeTab",
|
|
@@ -11,7 +11,9 @@
|
|
|
11
11
|
"tabs"
|
|
12
12
|
],
|
|
13
13
|
"host_permissions": [
|
|
14
|
-
"https://*.coupang.com/*"
|
|
14
|
+
"https://*.coupang.com/*",
|
|
15
|
+
"https://*.amazon.com/*",
|
|
16
|
+
"https://*.amazon.co.jp/*"
|
|
15
17
|
],
|
|
16
18
|
"background": {
|
|
17
19
|
"service_worker": "background.js",
|
|
@@ -26,6 +28,16 @@
|
|
|
26
28
|
"content/coupang.js"
|
|
27
29
|
],
|
|
28
30
|
"run_at": "document_idle"
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"matches": [
|
|
34
|
+
"https://*.amazon.com/*",
|
|
35
|
+
"https://*.amazon.co.jp/*"
|
|
36
|
+
],
|
|
37
|
+
"js": [
|
|
38
|
+
"content/amazon.js"
|
|
39
|
+
],
|
|
40
|
+
"run_at": "document_idle"
|
|
29
41
|
}
|
|
30
42
|
],
|
|
31
43
|
"action": {
|
|
@@ -33,4 +45,4 @@
|
|
|
33
45
|
"default_popup": "popup.html"
|
|
34
46
|
},
|
|
35
47
|
"minimum_chrome_version": "120"
|
|
36
|
-
}
|
|
48
|
+
}
|
package/dist/native-host.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
// @bun
|
|
3
|
-
import{createServer as q}from"net";import{existsSync as f,mkdirSync as w,readFileSync as b,rmSync as m}from"fs";import{homedir as R}from"os";import{dirname as g,join as h}from"path";import{fileURLToPath as V}from"url";var x="0.0.0-dev",E="0.
|
|
3
|
+
import{createServer as q}from"net";import{existsSync as f,mkdirSync as w,readFileSync as b,rmSync as m}from"fs";import{homedir as R}from"os";import{dirname as g,join as h}from"path";import{fileURLToPath as V}from"url";var x="0.0.0-dev",E="0.4.0",A=()=>{let e=g(V(import.meta.url));while(!0){let t=h(e,"package.json");if(f(t)){let o=JSON.parse(b(t,"utf8"));if(typeof o.version==="string"&&o.version.trim().length>0)return o.version}let r=g(e);if(r===e)break;e=r}return E==="0.4.0"?x:E},B=A(),T=1,c=h(R(),".buygent","chrome-extension","com.buygent.host.sock"),n=Buffer.alloc(0),s=new Map,p=new Map,l=new WeakMap,i=()=>globalThis.crypto?.randomUUID?.()??`req_${Date.now()}_${Math.random().toString(16).slice(2)}`,_=(e,t,r)=>({protocolVersion:T,type:e,messageId:r.messageId,...r.requestId?{requestId:r.requestId}:{},sentAt:r.sentAt??new Date().toISOString(),source:r.source,payload:t}),d=(e,t)=>_("error",e,t),O=(e)=>{if(!e||typeof e!=="object"||Array.isArray(e))return{ok:!1,error:d({code:"invalid_envelope",message:"Expected a JSON object envelope."},{source:"native-host",messageId:i()})};let t=e;if(t.protocolVersion!==T)return{ok:!1,error:d({code:"unsupported_protocol_version",message:`Unsupported protocolVersion: ${String(t.protocolVersion??"missing")}`},{source:"native-host",messageId:i()})};if(typeof t.type!=="string"||typeof t.messageId!=="string"||typeof t.sentAt!=="string"||typeof t.source!=="string")return{ok:!1,error:d({code:"invalid_envelope",message:"Envelope must include type, messageId, sentAt, and source fields."},{source:"native-host",messageId:i()})};return{ok:!0,envelope:e}},D=(e)=>JSON.stringify(e),u=(e)=>{let t=Buffer.from(JSON.stringify(e),"utf8"),r=Buffer.alloc(4);r.writeUInt32LE(t.length,0),process.stdout.write(r),process.stdout.write(t)},a=(e,t)=>{e.write(`${D(t)}
|
|
4
4
|
`)},P=(e,t)=>{let r=p.get(e)??new Set;r.add(t),p.set(e,r)},S=(e)=>{for(let[t,r]of p.entries())if(r.delete(e),r.size===0)p.delete(t);for(let[t,r]of s.entries())if(r===e)s.delete(t)},k=(e,t)=>{let r=p.get(e);if(!r)return;for(let o of r)a(o,t)},U=(e)=>{if(e.type==="native:ping"){u(_("native:pong",{hostVersion:B,receivedAt:new Date().toISOString()},{source:"native-host",messageId:i(),requestId:e.messageId}));return}if(e.type==="order:ack"){if(e.requestId){let t=s.get(e.requestId);if(t)P(e.payload.orderId,t),a(t,e)}return}if(e.type==="runtime:state"){if(e.requestId){let t=s.get(e.requestId);if(t)s.delete(e.requestId),a(t,e)}return}if(e.type==="order:status"||e.type==="order:checkpoint"){k(e.payload.orderId,e);return}if(e.type==="error"){let t=typeof e.payload.details==="object"&&e.payload.details&&!Array.isArray(e.payload.details)?e.payload.details.orderId:void 0;if(typeof t==="string"){k(t,e);return}if(e.requestId){let r=s.get(e.requestId);if(r)s.delete(e.requestId),a(r,e)}}},L=(e)=>{let t=O(e);if(!t.ok){u(t.error);return}U(t.envelope)},H=(e,t)=>{let r=O(JSON.parse(t));if(!r.ok){a(e,r.error);return}let o=r.envelope;if(o.type==="order:start"||o.type==="runtime:get-state"){s.set(o.messageId,e),u(o);return}a(e,d({code:"unsupported_message",message:`Unsupported CLI/native-host message: ${o.type}`},{source:"native-host",messageId:i(),requestId:o.messageId}))},J=()=>{if(w(g(c),{recursive:!0,mode:448}),f(c))m(c,{force:!0})};J();var M=q((e)=>{e.setEncoding("utf8"),l.set(e,""),e.on("data",(t)=>{let o=`${l.get(e)??""}${t}`.split(/\r?\n/u);l.set(e,o.pop()??"");for(let N of o){let y=N.trim();if(!y)continue;try{H(e,y)}catch(I){a(e,d({code:"invalid_message",message:I instanceof Error?I.message:"Invalid CLI/native-host payload."},{source:"native-host",messageId:i()}))}}}),e.on("close",()=>{S(e)}),e.on("error",()=>{S(e)})});M.listen(c);process.stdin.on("data",(e)=>{n=Buffer.concat([n,e]);while(n.length>=4){let t=n.readUInt32LE(0);if(n.length<4+t)return;let r=n.subarray(4,4+t);n=n.subarray(4+t);try{L(JSON.parse(r.toString("utf8")))}catch(o){u(d({code:"invalid_message",message:o instanceof Error?o.message:"Invalid JSON payload."},{source:"native-host",messageId:i()}))}}});var v=()=>{if(M.close(),f(c))m(c,{force:!0})};process.stdin.on("end",()=>{v(),process.exit(0)});process.on("SIGTERM",()=>{v(),process.exit(0)});process.on("SIGINT",()=>{v(),process.exit(0)});process.stdin.resume();
|