@buygent/cli 0.3.10 → 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.
@@ -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
+ })();
@@ -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 Coupang session probing and native host connectivity.",
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
+ }
@@ -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.10",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.3.10"?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)}
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();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@buygent/cli",
3
- "version": "0.3.10",
3
+ "version": "0.4.0",
4
4
  "description": "Buygent CLI for one-command installation and extension setup.",
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",