@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.
@@ -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
- while (Date.now() < deadline) {
676
- try {
677
- element.click();
678
- } catch {}
679
- await wait2(intervalMs);
680
- const currentUrl = getCurrentUrl();
681
- const navigated = options?.expectedUrlPattern ? options.expectedUrlPattern.test(currentUrl) : currentUrl !== startUrl;
682
- if (navigated) {
683
- return true;
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 navigated = await clickAndAwaitNavigation(found, {
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("Coupang did not navigate to checkout after clicking the cart order button.");
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 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.9",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.9"?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.9",
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",