letsfg 1.4.2 → 1.7.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/README.md +2 -2
- package/dist/{chunk-7LYR3CHE.mjs → chunk-RLP7MSF6.mjs} +41 -37
- package/dist/cli.js +126 -82
- package/dist/cli.mjs +39 -55
- package/dist/index.d.mts +9 -25
- package/dist/index.d.ts +9 -25
- package/dist/index.js +41 -38
- package/dist/index.mjs +1 -3
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# LetsFG — Your AI agent just learned to book flights. (Node.js)
|
|
2
2
|
|
|
3
|
-
**
|
|
3
|
+
**200 airlines. Real prices. One function call.** Search 400+ airlines at raw airline prices — **$20–$50 cheaper** than Booking.com, Kayak, and other OTAs. Zero dependencies. Built for AI agents.
|
|
4
4
|
|
|
5
5
|
> **Don't want to install anything?** [**Try it on Messenger**](https://m.me/61579557368989) — search flights instantly, no setup needed.
|
|
6
6
|
|
|
@@ -81,7 +81,7 @@ letsfg book off_xxx -p '{"id":"pas_xxx","given_name":"John",...}' -e john@exampl
|
|
|
81
81
|
|
|
82
82
|
### `searchLocal(origin, destination, dateFrom, options?)`
|
|
83
83
|
|
|
84
|
-
Search
|
|
84
|
+
Search 200 airline connectors locally (no API key needed). Requires Python + `letsfg` installed.
|
|
85
85
|
|
|
86
86
|
```typescript
|
|
87
87
|
import { searchLocal } from 'letsfg';
|
|
@@ -106,12 +106,6 @@ var ValidationError = class extends LetsFGError {
|
|
|
106
106
|
this.name = "ValidationError";
|
|
107
107
|
}
|
|
108
108
|
};
|
|
109
|
-
var StarRequiredError = class extends LetsFGError {
|
|
110
|
-
constructor(message = "GitHub star required. Run: letsfg star --github <your-username>") {
|
|
111
|
-
super(message, 403, {}, "STAR_REQUIRED");
|
|
112
|
-
this.name = "StarRequiredError";
|
|
113
|
-
}
|
|
114
|
-
};
|
|
115
109
|
function routeStr(route) {
|
|
116
110
|
if (!route.segments.length) return "";
|
|
117
111
|
const codes = [route.segments[0].origin, ...route.segments.map((s) => s.destination)];
|
|
@@ -162,13 +156,8 @@ async function searchLocal(origin, destination, dateFrom, options = {}) {
|
|
|
162
156
|
child.on("close", (code) => {
|
|
163
157
|
try {
|
|
164
158
|
const data = JSON.parse(stdout);
|
|
165
|
-
if (data.error)
|
|
166
|
-
|
|
167
|
-
reject(new StarRequiredError(data.error));
|
|
168
|
-
} else {
|
|
169
|
-
reject(new LetsFGError(data.error));
|
|
170
|
-
}
|
|
171
|
-
} else resolve(data);
|
|
159
|
+
if (data.error) reject(new LetsFGError(data.error));
|
|
160
|
+
else resolve(data);
|
|
172
161
|
} catch {
|
|
173
162
|
reject(new LetsFGError(
|
|
174
163
|
`Python search failed (code ${code}): ${stdout || stderr}
|
|
@@ -205,7 +194,10 @@ var LetsFG = class {
|
|
|
205
194
|
}
|
|
206
195
|
// ── Core methods ─────────────────────────────────────────────────────
|
|
207
196
|
/**
|
|
208
|
-
* Search for flights — FREE, unlimited.
|
|
197
|
+
* Search for flights — FREE, unlimited, runs locally on your machine.
|
|
198
|
+
*
|
|
199
|
+
* Uses 200 airline connectors via Python subprocess. No backend call.
|
|
200
|
+
* Requires: pip install letsfg && playwright install chromium
|
|
209
201
|
*
|
|
210
202
|
* @param origin - IATA code (e.g., "GDN", "LON")
|
|
211
203
|
* @param destination - IATA code (e.g., "BER", "BCN")
|
|
@@ -213,32 +205,44 @@ var LetsFG = class {
|
|
|
213
205
|
* @param options - Optional search parameters
|
|
214
206
|
*/
|
|
215
207
|
async search(origin, destination, dateFrom, options = {}) {
|
|
216
|
-
|
|
217
|
-
const body = {
|
|
218
|
-
origin: origin.toUpperCase(),
|
|
219
|
-
destination: destination.toUpperCase(),
|
|
220
|
-
date_from: dateFrom,
|
|
221
|
-
adults: options.adults ?? 1,
|
|
222
|
-
children: options.children ?? 0,
|
|
223
|
-
infants: options.infants ?? 0,
|
|
224
|
-
max_stopovers: options.maxStopovers ?? 2,
|
|
225
|
-
currency: options.currency ?? "EUR",
|
|
226
|
-
limit: options.limit ?? 20,
|
|
227
|
-
sort: options.sort ?? "price"
|
|
228
|
-
};
|
|
229
|
-
if (options.returnDate) body.return_from = options.returnDate;
|
|
230
|
-
if (options.cabinClass) body.cabin_class = options.cabinClass;
|
|
231
|
-
return this.post("/api/v1/flights/search", body);
|
|
208
|
+
return searchLocal(origin, destination, dateFrom, options);
|
|
232
209
|
}
|
|
233
210
|
/**
|
|
234
|
-
* Resolve a city/airport name to IATA codes.
|
|
211
|
+
* Resolve a city/airport name to IATA codes — runs locally, no backend call.
|
|
235
212
|
*/
|
|
236
213
|
async resolveLocation(query) {
|
|
237
|
-
|
|
238
|
-
const
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
214
|
+
const { spawn } = await import("child_process");
|
|
215
|
+
const params = JSON.stringify({ __resolve_location: true, query });
|
|
216
|
+
return new Promise((resolve, reject) => {
|
|
217
|
+
const pythonCmd = process.platform === "win32" ? "python" : "python3";
|
|
218
|
+
const child = spawn(pythonCmd, ["-m", "letsfg.local"], {
|
|
219
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
220
|
+
});
|
|
221
|
+
let stdout = "";
|
|
222
|
+
let stderr = "";
|
|
223
|
+
child.stdout.on("data", (d) => {
|
|
224
|
+
stdout += d.toString();
|
|
225
|
+
});
|
|
226
|
+
child.stderr.on("data", (d) => {
|
|
227
|
+
stderr += d.toString();
|
|
228
|
+
});
|
|
229
|
+
child.on("close", (code) => {
|
|
230
|
+
try {
|
|
231
|
+
const data = JSON.parse(stdout);
|
|
232
|
+
if (data.error) reject(new LetsFGError(data.error));
|
|
233
|
+
else resolve(Array.isArray(data) ? data : data.locations || [data]);
|
|
234
|
+
} catch {
|
|
235
|
+
reject(new LetsFGError(
|
|
236
|
+
`Location resolution failed (code ${code}): ${stdout || stderr}`
|
|
237
|
+
));
|
|
238
|
+
}
|
|
239
|
+
});
|
|
240
|
+
child.on("error", (err) => {
|
|
241
|
+
reject(new LetsFGError(`Cannot start Python: ${err.message}`));
|
|
242
|
+
});
|
|
243
|
+
child.stdin.write(params);
|
|
244
|
+
child.stdin.end();
|
|
245
|
+
});
|
|
242
246
|
}
|
|
243
247
|
/**
|
|
244
248
|
* Unlock a flight offer — FREE with GitHub star.
|
|
@@ -402,6 +406,7 @@ var LetsFG = class {
|
|
|
402
406
|
"Content-Type": "application/json",
|
|
403
407
|
"X-API-Key": this.apiKey,
|
|
404
408
|
"User-Agent": "LetsFG-js/0.1.0",
|
|
409
|
+
"X-Client-Type": "js-sdk",
|
|
405
410
|
...init.headers || {}
|
|
406
411
|
},
|
|
407
412
|
signal: controller.signal
|
|
@@ -470,7 +475,6 @@ export {
|
|
|
470
475
|
PaymentRequiredError,
|
|
471
476
|
OfferExpiredError,
|
|
472
477
|
ValidationError,
|
|
473
|
-
StarRequiredError,
|
|
474
478
|
offerSummary,
|
|
475
479
|
cheapestOffer,
|
|
476
480
|
searchLocal,
|
package/dist/cli.js
CHANGED
|
@@ -131,12 +131,6 @@ var ValidationError = class extends LetsFGError {
|
|
|
131
131
|
this.name = "ValidationError";
|
|
132
132
|
}
|
|
133
133
|
};
|
|
134
|
-
var StarRequiredError = class extends LetsFGError {
|
|
135
|
-
constructor(message = "GitHub star required. Run: letsfg star --github <your-username>") {
|
|
136
|
-
super(message, 403, {}, "STAR_REQUIRED");
|
|
137
|
-
this.name = "StarRequiredError";
|
|
138
|
-
}
|
|
139
|
-
};
|
|
140
134
|
function routeStr(route) {
|
|
141
135
|
if (!route.segments.length) return "";
|
|
142
136
|
const codes = [route.segments[0].origin, ...route.segments.map((s) => s.destination)];
|
|
@@ -153,6 +147,55 @@ function offerSummary(offer) {
|
|
|
153
147
|
const airline = offer.owner_airline || offer.airlines[0] || "?";
|
|
154
148
|
return `${offer.currency} ${offer.price.toFixed(2)} | ${airline} | ${route} | ${dur} | ${offer.outbound.stopovers} stop(s)`;
|
|
155
149
|
}
|
|
150
|
+
async function searchLocal(origin, destination, dateFrom, options = {}) {
|
|
151
|
+
const { spawn } = await import("child_process");
|
|
152
|
+
const params = JSON.stringify({
|
|
153
|
+
origin: origin.toUpperCase(),
|
|
154
|
+
destination: destination.toUpperCase(),
|
|
155
|
+
date_from: dateFrom,
|
|
156
|
+
adults: options.adults ?? 1,
|
|
157
|
+
children: options.children ?? 0,
|
|
158
|
+
currency: options.currency ?? "EUR",
|
|
159
|
+
limit: options.limit ?? 50,
|
|
160
|
+
return_date: options.returnDate,
|
|
161
|
+
cabin_class: options.cabinClass,
|
|
162
|
+
...options.maxBrowsers != null && { max_browsers: options.maxBrowsers }
|
|
163
|
+
});
|
|
164
|
+
return new Promise((resolve, reject) => {
|
|
165
|
+
const pythonCmd = process.platform === "win32" ? "python" : "python3";
|
|
166
|
+
const child = spawn(pythonCmd, ["-m", "letsfg.local"], {
|
|
167
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
168
|
+
});
|
|
169
|
+
let stdout = "";
|
|
170
|
+
let stderr = "";
|
|
171
|
+
child.stdout.on("data", (d) => {
|
|
172
|
+
stdout += d.toString();
|
|
173
|
+
});
|
|
174
|
+
child.stderr.on("data", (d) => {
|
|
175
|
+
stderr += d.toString();
|
|
176
|
+
});
|
|
177
|
+
child.on("close", (code) => {
|
|
178
|
+
try {
|
|
179
|
+
const data = JSON.parse(stdout);
|
|
180
|
+
if (data.error) reject(new LetsFGError(data.error));
|
|
181
|
+
else resolve(data);
|
|
182
|
+
} catch {
|
|
183
|
+
reject(new LetsFGError(
|
|
184
|
+
`Python search failed (code ${code}): ${stdout || stderr}
|
|
185
|
+
Make sure LetsFG is installed: pip install letsfg && playwright install chromium`
|
|
186
|
+
));
|
|
187
|
+
}
|
|
188
|
+
});
|
|
189
|
+
child.on("error", (err) => {
|
|
190
|
+
reject(new LetsFGError(
|
|
191
|
+
`Cannot start Python: ${err.message}
|
|
192
|
+
Install: pip install letsfg && playwright install chromium`
|
|
193
|
+
));
|
|
194
|
+
});
|
|
195
|
+
child.stdin.write(params);
|
|
196
|
+
child.stdin.end();
|
|
197
|
+
});
|
|
198
|
+
}
|
|
156
199
|
var DEFAULT_BASE_URL = "https://api.letsfg.co";
|
|
157
200
|
var LetsFG = class {
|
|
158
201
|
apiKey;
|
|
@@ -172,7 +215,10 @@ var LetsFG = class {
|
|
|
172
215
|
}
|
|
173
216
|
// ── Core methods ─────────────────────────────────────────────────────
|
|
174
217
|
/**
|
|
175
|
-
* Search for flights — FREE, unlimited.
|
|
218
|
+
* Search for flights — FREE, unlimited, runs locally on your machine.
|
|
219
|
+
*
|
|
220
|
+
* Uses 200 airline connectors via Python subprocess. No backend call.
|
|
221
|
+
* Requires: pip install letsfg && playwright install chromium
|
|
176
222
|
*
|
|
177
223
|
* @param origin - IATA code (e.g., "GDN", "LON")
|
|
178
224
|
* @param destination - IATA code (e.g., "BER", "BCN")
|
|
@@ -180,32 +226,44 @@ var LetsFG = class {
|
|
|
180
226
|
* @param options - Optional search parameters
|
|
181
227
|
*/
|
|
182
228
|
async search(origin, destination, dateFrom, options = {}) {
|
|
183
|
-
|
|
184
|
-
const body = {
|
|
185
|
-
origin: origin.toUpperCase(),
|
|
186
|
-
destination: destination.toUpperCase(),
|
|
187
|
-
date_from: dateFrom,
|
|
188
|
-
adults: options.adults ?? 1,
|
|
189
|
-
children: options.children ?? 0,
|
|
190
|
-
infants: options.infants ?? 0,
|
|
191
|
-
max_stopovers: options.maxStopovers ?? 2,
|
|
192
|
-
currency: options.currency ?? "EUR",
|
|
193
|
-
limit: options.limit ?? 20,
|
|
194
|
-
sort: options.sort ?? "price"
|
|
195
|
-
};
|
|
196
|
-
if (options.returnDate) body.return_from = options.returnDate;
|
|
197
|
-
if (options.cabinClass) body.cabin_class = options.cabinClass;
|
|
198
|
-
return this.post("/api/v1/flights/search", body);
|
|
229
|
+
return searchLocal(origin, destination, dateFrom, options);
|
|
199
230
|
}
|
|
200
231
|
/**
|
|
201
|
-
* Resolve a city/airport name to IATA codes.
|
|
232
|
+
* Resolve a city/airport name to IATA codes — runs locally, no backend call.
|
|
202
233
|
*/
|
|
203
234
|
async resolveLocation(query) {
|
|
204
|
-
|
|
205
|
-
const
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
235
|
+
const { spawn } = await import("child_process");
|
|
236
|
+
const params = JSON.stringify({ __resolve_location: true, query });
|
|
237
|
+
return new Promise((resolve, reject) => {
|
|
238
|
+
const pythonCmd = process.platform === "win32" ? "python" : "python3";
|
|
239
|
+
const child = spawn(pythonCmd, ["-m", "letsfg.local"], {
|
|
240
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
241
|
+
});
|
|
242
|
+
let stdout = "";
|
|
243
|
+
let stderr = "";
|
|
244
|
+
child.stdout.on("data", (d) => {
|
|
245
|
+
stdout += d.toString();
|
|
246
|
+
});
|
|
247
|
+
child.stderr.on("data", (d) => {
|
|
248
|
+
stderr += d.toString();
|
|
249
|
+
});
|
|
250
|
+
child.on("close", (code) => {
|
|
251
|
+
try {
|
|
252
|
+
const data = JSON.parse(stdout);
|
|
253
|
+
if (data.error) reject(new LetsFGError(data.error));
|
|
254
|
+
else resolve(Array.isArray(data) ? data : data.locations || [data]);
|
|
255
|
+
} catch {
|
|
256
|
+
reject(new LetsFGError(
|
|
257
|
+
`Location resolution failed (code ${code}): ${stdout || stderr}`
|
|
258
|
+
));
|
|
259
|
+
}
|
|
260
|
+
});
|
|
261
|
+
child.on("error", (err) => {
|
|
262
|
+
reject(new LetsFGError(`Cannot start Python: ${err.message}`));
|
|
263
|
+
});
|
|
264
|
+
child.stdin.write(params);
|
|
265
|
+
child.stdin.end();
|
|
266
|
+
});
|
|
209
267
|
}
|
|
210
268
|
/**
|
|
211
269
|
* Unlock a flight offer — FREE with GitHub star.
|
|
@@ -369,6 +427,7 @@ var LetsFG = class {
|
|
|
369
427
|
"Content-Type": "application/json",
|
|
370
428
|
"X-API-Key": this.apiKey,
|
|
371
429
|
"User-Agent": "LetsFG-js/0.1.0",
|
|
430
|
+
"X-Client-Type": "js-sdk",
|
|
372
431
|
...init.headers || {}
|
|
373
432
|
},
|
|
374
433
|
signal: controller.signal
|
|
@@ -610,44 +669,42 @@ async function cmdRegister(args) {
|
|
|
610
669
|
}
|
|
611
670
|
async function cmdStar(args) {
|
|
612
671
|
const jsonOut = hasFlag(args, "--json") || hasFlag(args, "-j");
|
|
672
|
+
const apiKey = getFlag(args, "--api-key", "-k");
|
|
673
|
+
const baseUrl = getFlag(args, "--base-url");
|
|
613
674
|
const github = getFlag(args, "--github", "-g");
|
|
614
675
|
if (!github) {
|
|
615
676
|
console.error("Usage: letsfg star --github <your-github-username>");
|
|
616
677
|
process.exit(1);
|
|
617
678
|
}
|
|
618
|
-
const
|
|
619
|
-
const
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
});
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
});
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
console.error("Install: pip install letsfg");
|
|
648
|
-
process.exit(1);
|
|
649
|
-
});
|
|
650
|
-
});
|
|
679
|
+
const bt = new LetsFG({ apiKey, baseUrl });
|
|
680
|
+
const result = await bt.linkGithub(github);
|
|
681
|
+
if (jsonOut) {
|
|
682
|
+
console.log(JSON.stringify(result, null, 2));
|
|
683
|
+
return;
|
|
684
|
+
}
|
|
685
|
+
const status = result.status;
|
|
686
|
+
if (status === "verified") {
|
|
687
|
+
console.log(`
|
|
688
|
+
\u2713 GitHub star verified! Unlimited access granted.`);
|
|
689
|
+
console.log(` Username: ${result.github_username}`);
|
|
690
|
+
console.log(`
|
|
691
|
+
You're all set \u2014 search, unlock, and book for free.
|
|
692
|
+
`);
|
|
693
|
+
} else if (status === "already_verified") {
|
|
694
|
+
console.log(`
|
|
695
|
+
\u2713 Already verified! You have unlimited access.`);
|
|
696
|
+
console.log(` Username: ${result.github_username}
|
|
697
|
+
`);
|
|
698
|
+
} else if (status === "star_required") {
|
|
699
|
+
console.log(`
|
|
700
|
+
\u2717 Star not found for '${github}'.`);
|
|
701
|
+
console.log(` 1. Star the repo: https://github.com/LetsFG/LetsFG`);
|
|
702
|
+
console.log(` 2. Run this command again.
|
|
703
|
+
`);
|
|
704
|
+
} else {
|
|
705
|
+
console.error(` \u2717 Unexpected status: ${status}`);
|
|
706
|
+
process.exit(1);
|
|
707
|
+
}
|
|
651
708
|
}
|
|
652
709
|
async function cmdSetupPayment(args) {
|
|
653
710
|
const jsonOut = hasFlag(args, "--json") || hasFlag(args, "-j");
|
|
@@ -705,19 +762,16 @@ var HELP = `
|
|
|
705
762
|
LetsFG \u2014 Agent-native flight search & booking.
|
|
706
763
|
|
|
707
764
|
Search 400+ airlines at raw airline prices \u2014 $20-50 cheaper than OTAs.
|
|
708
|
-
|
|
709
|
-
**GitHub Star Required!**
|
|
710
|
-
Before using, you must:
|
|
711
|
-
1. Star https://github.com/LetsFG/LetsFG
|
|
712
|
-
2. Run: letsfg star --github <your-username>
|
|
765
|
+
100% FREE \u2014 just star our GitHub repo for unlimited access.
|
|
713
766
|
|
|
714
767
|
Commands:
|
|
715
|
-
|
|
716
|
-
search <origin> <dest> <date> Search for flights (FREE with star)
|
|
768
|
+
search <origin> <dest> <date> Search for flights (FREE)
|
|
717
769
|
locations <query> Resolve city name to IATA codes
|
|
718
|
-
|
|
719
|
-
|
|
770
|
+
star --github <username> Link GitHub \u2014 star repo for free access
|
|
771
|
+
unlock <offer_id> Unlock offer (FREE with GitHub star)
|
|
772
|
+
book <offer_id> --passenger ... Book flight (FREE after unlock)
|
|
720
773
|
register --name ... --email ... Register new agent
|
|
774
|
+
setup-payment Legacy payment setup
|
|
721
775
|
me Show agent profile
|
|
722
776
|
|
|
723
777
|
Options:
|
|
@@ -726,6 +780,7 @@ Options:
|
|
|
726
780
|
--base-url API URL (default: https://api.letsfg.co)
|
|
727
781
|
|
|
728
782
|
Examples:
|
|
783
|
+
letsfg register --name my-agent --email me@example.com
|
|
729
784
|
letsfg star --github octocat
|
|
730
785
|
letsfg search GDN BER 2026-03-03 --sort price
|
|
731
786
|
letsfg unlock off_xxx
|
|
@@ -772,17 +827,6 @@ async function main() {
|
|
|
772
827
|
process.exit(1);
|
|
773
828
|
}
|
|
774
829
|
} catch (e) {
|
|
775
|
-
if (e instanceof StarRequiredError) {
|
|
776
|
-
console.error(`
|
|
777
|
-
\u2B50 GitHub star required to use LetsFG!
|
|
778
|
-
`);
|
|
779
|
-
console.error(` 1. Star the repo: https://github.com/LetsFG/LetsFG`);
|
|
780
|
-
console.error(` 2. Run: letsfg star --github <your-username>
|
|
781
|
-
`);
|
|
782
|
-
console.error(` This is completely FREE \u2014 just a star to help us grow!
|
|
783
|
-
`);
|
|
784
|
-
process.exit(1);
|
|
785
|
-
}
|
|
786
830
|
if (e instanceof LetsFGError) {
|
|
787
831
|
console.error(`Error: ${e.message}`);
|
|
788
832
|
process.exit(1);
|
package/dist/cli.mjs
CHANGED
|
@@ -2,9 +2,8 @@
|
|
|
2
2
|
import {
|
|
3
3
|
LetsFG,
|
|
4
4
|
LetsFGError,
|
|
5
|
-
StarRequiredError,
|
|
6
5
|
offerSummary
|
|
7
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-RLP7MSF6.mjs";
|
|
8
7
|
|
|
9
8
|
// src/cli.ts
|
|
10
9
|
function getFlag(args, flag, alias) {
|
|
@@ -226,44 +225,42 @@ async function cmdRegister(args) {
|
|
|
226
225
|
}
|
|
227
226
|
async function cmdStar(args) {
|
|
228
227
|
const jsonOut = hasFlag(args, "--json") || hasFlag(args, "-j");
|
|
228
|
+
const apiKey = getFlag(args, "--api-key", "-k");
|
|
229
|
+
const baseUrl = getFlag(args, "--base-url");
|
|
229
230
|
const github = getFlag(args, "--github", "-g");
|
|
230
231
|
if (!github) {
|
|
231
232
|
console.error("Usage: letsfg star --github <your-github-username>");
|
|
232
233
|
process.exit(1);
|
|
233
234
|
}
|
|
234
|
-
const
|
|
235
|
-
const
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
});
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
});
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
console.error("Install: pip install letsfg");
|
|
264
|
-
process.exit(1);
|
|
265
|
-
});
|
|
266
|
-
});
|
|
235
|
+
const bt = new LetsFG({ apiKey, baseUrl });
|
|
236
|
+
const result = await bt.linkGithub(github);
|
|
237
|
+
if (jsonOut) {
|
|
238
|
+
console.log(JSON.stringify(result, null, 2));
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
241
|
+
const status = result.status;
|
|
242
|
+
if (status === "verified") {
|
|
243
|
+
console.log(`
|
|
244
|
+
\u2713 GitHub star verified! Unlimited access granted.`);
|
|
245
|
+
console.log(` Username: ${result.github_username}`);
|
|
246
|
+
console.log(`
|
|
247
|
+
You're all set \u2014 search, unlock, and book for free.
|
|
248
|
+
`);
|
|
249
|
+
} else if (status === "already_verified") {
|
|
250
|
+
console.log(`
|
|
251
|
+
\u2713 Already verified! You have unlimited access.`);
|
|
252
|
+
console.log(` Username: ${result.github_username}
|
|
253
|
+
`);
|
|
254
|
+
} else if (status === "star_required") {
|
|
255
|
+
console.log(`
|
|
256
|
+
\u2717 Star not found for '${github}'.`);
|
|
257
|
+
console.log(` 1. Star the repo: https://github.com/LetsFG/LetsFG`);
|
|
258
|
+
console.log(` 2. Run this command again.
|
|
259
|
+
`);
|
|
260
|
+
} else {
|
|
261
|
+
console.error(` \u2717 Unexpected status: ${status}`);
|
|
262
|
+
process.exit(1);
|
|
263
|
+
}
|
|
267
264
|
}
|
|
268
265
|
async function cmdSetupPayment(args) {
|
|
269
266
|
const jsonOut = hasFlag(args, "--json") || hasFlag(args, "-j");
|
|
@@ -321,19 +318,16 @@ var HELP = `
|
|
|
321
318
|
LetsFG \u2014 Agent-native flight search & booking.
|
|
322
319
|
|
|
323
320
|
Search 400+ airlines at raw airline prices \u2014 $20-50 cheaper than OTAs.
|
|
324
|
-
|
|
325
|
-
**GitHub Star Required!**
|
|
326
|
-
Before using, you must:
|
|
327
|
-
1. Star https://github.com/LetsFG/LetsFG
|
|
328
|
-
2. Run: letsfg star --github <your-username>
|
|
321
|
+
100% FREE \u2014 just star our GitHub repo for unlimited access.
|
|
329
322
|
|
|
330
323
|
Commands:
|
|
331
|
-
|
|
332
|
-
search <origin> <dest> <date> Search for flights (FREE with star)
|
|
324
|
+
search <origin> <dest> <date> Search for flights (FREE)
|
|
333
325
|
locations <query> Resolve city name to IATA codes
|
|
334
|
-
|
|
335
|
-
|
|
326
|
+
star --github <username> Link GitHub \u2014 star repo for free access
|
|
327
|
+
unlock <offer_id> Unlock offer (FREE with GitHub star)
|
|
328
|
+
book <offer_id> --passenger ... Book flight (FREE after unlock)
|
|
336
329
|
register --name ... --email ... Register new agent
|
|
330
|
+
setup-payment Legacy payment setup
|
|
337
331
|
me Show agent profile
|
|
338
332
|
|
|
339
333
|
Options:
|
|
@@ -342,6 +336,7 @@ Options:
|
|
|
342
336
|
--base-url API URL (default: https://api.letsfg.co)
|
|
343
337
|
|
|
344
338
|
Examples:
|
|
339
|
+
letsfg register --name my-agent --email me@example.com
|
|
345
340
|
letsfg star --github octocat
|
|
346
341
|
letsfg search GDN BER 2026-03-03 --sort price
|
|
347
342
|
letsfg unlock off_xxx
|
|
@@ -388,17 +383,6 @@ async function main() {
|
|
|
388
383
|
process.exit(1);
|
|
389
384
|
}
|
|
390
385
|
} catch (e) {
|
|
391
|
-
if (e instanceof StarRequiredError) {
|
|
392
|
-
console.error(`
|
|
393
|
-
\u2B50 GitHub star required to use LetsFG!
|
|
394
|
-
`);
|
|
395
|
-
console.error(` 1. Star the repo: https://github.com/LetsFG/LetsFG`);
|
|
396
|
-
console.error(` 2. Run: letsfg star --github <your-username>
|
|
397
|
-
`);
|
|
398
|
-
console.error(` This is completely FREE \u2014 just a star to help us grow!
|
|
399
|
-
`);
|
|
400
|
-
process.exit(1);
|
|
401
|
-
}
|
|
402
386
|
if (e instanceof LetsFGError) {
|
|
403
387
|
console.error(`Error: ${e.message}`);
|
|
404
388
|
process.exit(1);
|
package/dist/index.d.mts
CHANGED
|
@@ -1,19 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* LetsFG — Agent-native flight search & booking SDK for Node.js/TypeScript.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* 75 airline connectors run locally via Python + backend API for enterprise GDS/NDC sources.
|
|
5
5
|
* Zero external JS dependencies. Uses native fetch (Node 18+).
|
|
6
6
|
*
|
|
7
|
-
* **GitHub Star Required!**
|
|
8
|
-
* Before using, you must:
|
|
9
|
-
* 1. Star https://github.com/LetsFG/LetsFG
|
|
10
|
-
* 2. Run: letsfg star --github <your-username>
|
|
11
|
-
*
|
|
12
7
|
* @example
|
|
13
8
|
* ```ts
|
|
14
9
|
* import { LetsFG, searchLocal } from 'letsfg';
|
|
15
10
|
*
|
|
16
|
-
* // Local search — FREE
|
|
11
|
+
* // Local search — FREE, no API key
|
|
17
12
|
* const local = await searchLocal('SHA', 'CTU', '2026-03-20');
|
|
18
13
|
*
|
|
19
14
|
* // Full API — search + unlock + book
|
|
@@ -188,25 +183,12 @@ declare class OfferExpiredError extends LetsFGError {
|
|
|
188
183
|
declare class ValidationError extends LetsFGError {
|
|
189
184
|
constructor(message: string, statusCode?: number, response?: Record<string, unknown>, errorCode?: string);
|
|
190
185
|
}
|
|
191
|
-
/**
|
|
192
|
-
* Thrown when GitHub star verification is required.
|
|
193
|
-
* Users must star https://github.com/LetsFG/LetsFG and run:
|
|
194
|
-
* letsfg star --github <username>
|
|
195
|
-
*/
|
|
196
|
-
declare class StarRequiredError extends LetsFGError {
|
|
197
|
-
constructor(message?: string);
|
|
198
|
-
}
|
|
199
186
|
/** One-line offer summary */
|
|
200
187
|
declare function offerSummary(offer: FlightOffer): string;
|
|
201
188
|
/** Get cheapest offer from search results */
|
|
202
189
|
declare function cheapestOffer(result: FlightSearchResult): FlightOffer | null;
|
|
203
190
|
/**
|
|
204
|
-
* Search flights using
|
|
205
|
-
*
|
|
206
|
-
* **GitHub Star Required!**
|
|
207
|
-
* Before using, you must:
|
|
208
|
-
* 1. Star https://github.com/LetsFG/LetsFG
|
|
209
|
-
* 2. Run: letsfg star --github <your-username>
|
|
191
|
+
* Search flights using 73 local airline connectors — FREE, no API key needed.
|
|
210
192
|
*
|
|
211
193
|
* Requires: pip install letsfg && playwright install chromium
|
|
212
194
|
*
|
|
@@ -214,7 +196,6 @@ declare function cheapestOffer(result: FlightSearchResult): FlightOffer | null;
|
|
|
214
196
|
* @param destination - IATA code (e.g., "CTU")
|
|
215
197
|
* @param dateFrom - Departure date "YYYY-MM-DD"
|
|
216
198
|
* @param options - Optional: currency, adults, limit, etc.
|
|
217
|
-
* @throws {StarRequiredError} If GitHub star not verified
|
|
218
199
|
*/
|
|
219
200
|
declare function searchLocal(origin: string, destination: string, dateFrom: string, options?: Partial<SearchOptions>): Promise<FlightSearchResult>;
|
|
220
201
|
declare class LetsFG {
|
|
@@ -224,7 +205,10 @@ declare class LetsFG {
|
|
|
224
205
|
constructor(config?: LetsFGConfig);
|
|
225
206
|
private requireApiKey;
|
|
226
207
|
/**
|
|
227
|
-
* Search for flights — FREE, unlimited.
|
|
208
|
+
* Search for flights — FREE, unlimited, runs locally on your machine.
|
|
209
|
+
*
|
|
210
|
+
* Uses 200 airline connectors via Python subprocess. No backend call.
|
|
211
|
+
* Requires: pip install letsfg && playwright install chromium
|
|
228
212
|
*
|
|
229
213
|
* @param origin - IATA code (e.g., "GDN", "LON")
|
|
230
214
|
* @param destination - IATA code (e.g., "BER", "BCN")
|
|
@@ -233,7 +217,7 @@ declare class LetsFG {
|
|
|
233
217
|
*/
|
|
234
218
|
search(origin: string, destination: string, dateFrom: string, options?: SearchOptions): Promise<FlightSearchResult>;
|
|
235
219
|
/**
|
|
236
|
-
* Resolve a city/airport name to IATA codes.
|
|
220
|
+
* Resolve a city/airport name to IATA codes — runs locally, no backend call.
|
|
237
221
|
*/
|
|
238
222
|
resolveLocation(query: string): Promise<Array<Record<string, unknown>>>;
|
|
239
223
|
/**
|
|
@@ -301,4 +285,4 @@ declare const BoostedTravel: typeof LetsFG;
|
|
|
301
285
|
declare const BoostedTravelError: typeof LetsFGError;
|
|
302
286
|
type BoostedTravelConfig = LetsFGConfig;
|
|
303
287
|
|
|
304
|
-
export { AuthenticationError, type BookingResult, BoostedTravel, type BoostedTravelConfig, BoostedTravelError, type CheckoutProgress, ErrorCategory, type ErrorCategoryType, ErrorCode, type ErrorCodeType, type FlightOffer, type FlightRoute, type FlightSearchResult, type FlightSegment, LetsFG, type LetsFGConfig, LetsFGError, OfferExpiredError, type Passenger, PaymentRequiredError, type SearchOptions,
|
|
288
|
+
export { AuthenticationError, type BookingResult, BoostedTravel, type BoostedTravelConfig, BoostedTravelError, type CheckoutProgress, ErrorCategory, type ErrorCategoryType, ErrorCode, type ErrorCodeType, type FlightOffer, type FlightRoute, type FlightSearchResult, type FlightSegment, LetsFG, type LetsFGConfig, LetsFGError, OfferExpiredError, type Passenger, PaymentRequiredError, type SearchOptions, type UnlockResult, ValidationError, cheapestOffer, LetsFG as default, systemInfo as getSystemInfo, searchLocal as localSearch, offerSummary, searchLocal, systemInfo };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,19 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* LetsFG — Agent-native flight search & booking SDK for Node.js/TypeScript.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* 75 airline connectors run locally via Python + backend API for enterprise GDS/NDC sources.
|
|
5
5
|
* Zero external JS dependencies. Uses native fetch (Node 18+).
|
|
6
6
|
*
|
|
7
|
-
* **GitHub Star Required!**
|
|
8
|
-
* Before using, you must:
|
|
9
|
-
* 1. Star https://github.com/LetsFG/LetsFG
|
|
10
|
-
* 2. Run: letsfg star --github <your-username>
|
|
11
|
-
*
|
|
12
7
|
* @example
|
|
13
8
|
* ```ts
|
|
14
9
|
* import { LetsFG, searchLocal } from 'letsfg';
|
|
15
10
|
*
|
|
16
|
-
* // Local search — FREE
|
|
11
|
+
* // Local search — FREE, no API key
|
|
17
12
|
* const local = await searchLocal('SHA', 'CTU', '2026-03-20');
|
|
18
13
|
*
|
|
19
14
|
* // Full API — search + unlock + book
|
|
@@ -188,25 +183,12 @@ declare class OfferExpiredError extends LetsFGError {
|
|
|
188
183
|
declare class ValidationError extends LetsFGError {
|
|
189
184
|
constructor(message: string, statusCode?: number, response?: Record<string, unknown>, errorCode?: string);
|
|
190
185
|
}
|
|
191
|
-
/**
|
|
192
|
-
* Thrown when GitHub star verification is required.
|
|
193
|
-
* Users must star https://github.com/LetsFG/LetsFG and run:
|
|
194
|
-
* letsfg star --github <username>
|
|
195
|
-
*/
|
|
196
|
-
declare class StarRequiredError extends LetsFGError {
|
|
197
|
-
constructor(message?: string);
|
|
198
|
-
}
|
|
199
186
|
/** One-line offer summary */
|
|
200
187
|
declare function offerSummary(offer: FlightOffer): string;
|
|
201
188
|
/** Get cheapest offer from search results */
|
|
202
189
|
declare function cheapestOffer(result: FlightSearchResult): FlightOffer | null;
|
|
203
190
|
/**
|
|
204
|
-
* Search flights using
|
|
205
|
-
*
|
|
206
|
-
* **GitHub Star Required!**
|
|
207
|
-
* Before using, you must:
|
|
208
|
-
* 1. Star https://github.com/LetsFG/LetsFG
|
|
209
|
-
* 2. Run: letsfg star --github <your-username>
|
|
191
|
+
* Search flights using 73 local airline connectors — FREE, no API key needed.
|
|
210
192
|
*
|
|
211
193
|
* Requires: pip install letsfg && playwright install chromium
|
|
212
194
|
*
|
|
@@ -214,7 +196,6 @@ declare function cheapestOffer(result: FlightSearchResult): FlightOffer | null;
|
|
|
214
196
|
* @param destination - IATA code (e.g., "CTU")
|
|
215
197
|
* @param dateFrom - Departure date "YYYY-MM-DD"
|
|
216
198
|
* @param options - Optional: currency, adults, limit, etc.
|
|
217
|
-
* @throws {StarRequiredError} If GitHub star not verified
|
|
218
199
|
*/
|
|
219
200
|
declare function searchLocal(origin: string, destination: string, dateFrom: string, options?: Partial<SearchOptions>): Promise<FlightSearchResult>;
|
|
220
201
|
declare class LetsFG {
|
|
@@ -224,7 +205,10 @@ declare class LetsFG {
|
|
|
224
205
|
constructor(config?: LetsFGConfig);
|
|
225
206
|
private requireApiKey;
|
|
226
207
|
/**
|
|
227
|
-
* Search for flights — FREE, unlimited.
|
|
208
|
+
* Search for flights — FREE, unlimited, runs locally on your machine.
|
|
209
|
+
*
|
|
210
|
+
* Uses 200 airline connectors via Python subprocess. No backend call.
|
|
211
|
+
* Requires: pip install letsfg && playwright install chromium
|
|
228
212
|
*
|
|
229
213
|
* @param origin - IATA code (e.g., "GDN", "LON")
|
|
230
214
|
* @param destination - IATA code (e.g., "BER", "BCN")
|
|
@@ -233,7 +217,7 @@ declare class LetsFG {
|
|
|
233
217
|
*/
|
|
234
218
|
search(origin: string, destination: string, dateFrom: string, options?: SearchOptions): Promise<FlightSearchResult>;
|
|
235
219
|
/**
|
|
236
|
-
* Resolve a city/airport name to IATA codes.
|
|
220
|
+
* Resolve a city/airport name to IATA codes — runs locally, no backend call.
|
|
237
221
|
*/
|
|
238
222
|
resolveLocation(query: string): Promise<Array<Record<string, unknown>>>;
|
|
239
223
|
/**
|
|
@@ -301,4 +285,4 @@ declare const BoostedTravel: typeof LetsFG;
|
|
|
301
285
|
declare const BoostedTravelError: typeof LetsFGError;
|
|
302
286
|
type BoostedTravelConfig = LetsFGConfig;
|
|
303
287
|
|
|
304
|
-
export { AuthenticationError, type BookingResult, BoostedTravel, type BoostedTravelConfig, BoostedTravelError, type CheckoutProgress, ErrorCategory, type ErrorCategoryType, ErrorCode, type ErrorCodeType, type FlightOffer, type FlightRoute, type FlightSearchResult, type FlightSegment, LetsFG, type LetsFGConfig, LetsFGError, OfferExpiredError, type Passenger, PaymentRequiredError, type SearchOptions,
|
|
288
|
+
export { AuthenticationError, type BookingResult, BoostedTravel, type BoostedTravelConfig, BoostedTravelError, type CheckoutProgress, ErrorCategory, type ErrorCategoryType, ErrorCode, type ErrorCodeType, type FlightOffer, type FlightRoute, type FlightSearchResult, type FlightSegment, LetsFG, type LetsFGConfig, LetsFGError, OfferExpiredError, type Passenger, PaymentRequiredError, type SearchOptions, type UnlockResult, ValidationError, cheapestOffer, LetsFG as default, systemInfo as getSystemInfo, searchLocal as localSearch, offerSummary, searchLocal, systemInfo };
|
package/dist/index.js
CHANGED
|
@@ -39,7 +39,6 @@ __export(index_exports, {
|
|
|
39
39
|
LetsFGError: () => LetsFGError,
|
|
40
40
|
OfferExpiredError: () => OfferExpiredError,
|
|
41
41
|
PaymentRequiredError: () => PaymentRequiredError,
|
|
42
|
-
StarRequiredError: () => StarRequiredError,
|
|
43
42
|
ValidationError: () => ValidationError,
|
|
44
43
|
cheapestOffer: () => cheapestOffer,
|
|
45
44
|
default: () => index_default,
|
|
@@ -157,12 +156,6 @@ var ValidationError = class extends LetsFGError {
|
|
|
157
156
|
this.name = "ValidationError";
|
|
158
157
|
}
|
|
159
158
|
};
|
|
160
|
-
var StarRequiredError = class extends LetsFGError {
|
|
161
|
-
constructor(message = "GitHub star required. Run: letsfg star --github <your-username>") {
|
|
162
|
-
super(message, 403, {}, "STAR_REQUIRED");
|
|
163
|
-
this.name = "StarRequiredError";
|
|
164
|
-
}
|
|
165
|
-
};
|
|
166
159
|
function routeStr(route) {
|
|
167
160
|
if (!route.segments.length) return "";
|
|
168
161
|
const codes = [route.segments[0].origin, ...route.segments.map((s) => s.destination)];
|
|
@@ -213,13 +206,8 @@ async function searchLocal(origin, destination, dateFrom, options = {}) {
|
|
|
213
206
|
child.on("close", (code) => {
|
|
214
207
|
try {
|
|
215
208
|
const data = JSON.parse(stdout);
|
|
216
|
-
if (data.error)
|
|
217
|
-
|
|
218
|
-
reject(new StarRequiredError(data.error));
|
|
219
|
-
} else {
|
|
220
|
-
reject(new LetsFGError(data.error));
|
|
221
|
-
}
|
|
222
|
-
} else resolve(data);
|
|
209
|
+
if (data.error) reject(new LetsFGError(data.error));
|
|
210
|
+
else resolve(data);
|
|
223
211
|
} catch {
|
|
224
212
|
reject(new LetsFGError(
|
|
225
213
|
`Python search failed (code ${code}): ${stdout || stderr}
|
|
@@ -256,7 +244,10 @@ var LetsFG = class {
|
|
|
256
244
|
}
|
|
257
245
|
// ── Core methods ─────────────────────────────────────────────────────
|
|
258
246
|
/**
|
|
259
|
-
* Search for flights — FREE, unlimited.
|
|
247
|
+
* Search for flights — FREE, unlimited, runs locally on your machine.
|
|
248
|
+
*
|
|
249
|
+
* Uses 200 airline connectors via Python subprocess. No backend call.
|
|
250
|
+
* Requires: pip install letsfg && playwright install chromium
|
|
260
251
|
*
|
|
261
252
|
* @param origin - IATA code (e.g., "GDN", "LON")
|
|
262
253
|
* @param destination - IATA code (e.g., "BER", "BCN")
|
|
@@ -264,32 +255,44 @@ var LetsFG = class {
|
|
|
264
255
|
* @param options - Optional search parameters
|
|
265
256
|
*/
|
|
266
257
|
async search(origin, destination, dateFrom, options = {}) {
|
|
267
|
-
|
|
268
|
-
const body = {
|
|
269
|
-
origin: origin.toUpperCase(),
|
|
270
|
-
destination: destination.toUpperCase(),
|
|
271
|
-
date_from: dateFrom,
|
|
272
|
-
adults: options.adults ?? 1,
|
|
273
|
-
children: options.children ?? 0,
|
|
274
|
-
infants: options.infants ?? 0,
|
|
275
|
-
max_stopovers: options.maxStopovers ?? 2,
|
|
276
|
-
currency: options.currency ?? "EUR",
|
|
277
|
-
limit: options.limit ?? 20,
|
|
278
|
-
sort: options.sort ?? "price"
|
|
279
|
-
};
|
|
280
|
-
if (options.returnDate) body.return_from = options.returnDate;
|
|
281
|
-
if (options.cabinClass) body.cabin_class = options.cabinClass;
|
|
282
|
-
return this.post("/api/v1/flights/search", body);
|
|
258
|
+
return searchLocal(origin, destination, dateFrom, options);
|
|
283
259
|
}
|
|
284
260
|
/**
|
|
285
|
-
* Resolve a city/airport name to IATA codes.
|
|
261
|
+
* Resolve a city/airport name to IATA codes — runs locally, no backend call.
|
|
286
262
|
*/
|
|
287
263
|
async resolveLocation(query) {
|
|
288
|
-
|
|
289
|
-
const
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
264
|
+
const { spawn } = await import("child_process");
|
|
265
|
+
const params = JSON.stringify({ __resolve_location: true, query });
|
|
266
|
+
return new Promise((resolve, reject) => {
|
|
267
|
+
const pythonCmd = process.platform === "win32" ? "python" : "python3";
|
|
268
|
+
const child = spawn(pythonCmd, ["-m", "letsfg.local"], {
|
|
269
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
270
|
+
});
|
|
271
|
+
let stdout = "";
|
|
272
|
+
let stderr = "";
|
|
273
|
+
child.stdout.on("data", (d) => {
|
|
274
|
+
stdout += d.toString();
|
|
275
|
+
});
|
|
276
|
+
child.stderr.on("data", (d) => {
|
|
277
|
+
stderr += d.toString();
|
|
278
|
+
});
|
|
279
|
+
child.on("close", (code) => {
|
|
280
|
+
try {
|
|
281
|
+
const data = JSON.parse(stdout);
|
|
282
|
+
if (data.error) reject(new LetsFGError(data.error));
|
|
283
|
+
else resolve(Array.isArray(data) ? data : data.locations || [data]);
|
|
284
|
+
} catch {
|
|
285
|
+
reject(new LetsFGError(
|
|
286
|
+
`Location resolution failed (code ${code}): ${stdout || stderr}`
|
|
287
|
+
));
|
|
288
|
+
}
|
|
289
|
+
});
|
|
290
|
+
child.on("error", (err) => {
|
|
291
|
+
reject(new LetsFGError(`Cannot start Python: ${err.message}`));
|
|
292
|
+
});
|
|
293
|
+
child.stdin.write(params);
|
|
294
|
+
child.stdin.end();
|
|
295
|
+
});
|
|
293
296
|
}
|
|
294
297
|
/**
|
|
295
298
|
* Unlock a flight offer — FREE with GitHub star.
|
|
@@ -453,6 +456,7 @@ var LetsFG = class {
|
|
|
453
456
|
"Content-Type": "application/json",
|
|
454
457
|
"X-API-Key": this.apiKey,
|
|
455
458
|
"User-Agent": "LetsFG-js/0.1.0",
|
|
459
|
+
"X-Client-Type": "js-sdk",
|
|
456
460
|
...init.headers || {}
|
|
457
461
|
},
|
|
458
462
|
signal: controller.signal
|
|
@@ -523,7 +527,6 @@ var BoostedTravelError = LetsFGError;
|
|
|
523
527
|
LetsFGError,
|
|
524
528
|
OfferExpiredError,
|
|
525
529
|
PaymentRequiredError,
|
|
526
|
-
StarRequiredError,
|
|
527
530
|
ValidationError,
|
|
528
531
|
cheapestOffer,
|
|
529
532
|
getSystemInfo,
|
package/dist/index.mjs
CHANGED
|
@@ -8,14 +8,13 @@ import {
|
|
|
8
8
|
LetsFGError,
|
|
9
9
|
OfferExpiredError,
|
|
10
10
|
PaymentRequiredError,
|
|
11
|
-
StarRequiredError,
|
|
12
11
|
ValidationError,
|
|
13
12
|
cheapestOffer,
|
|
14
13
|
index_default,
|
|
15
14
|
offerSummary,
|
|
16
15
|
searchLocal,
|
|
17
16
|
systemInfo
|
|
18
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-RLP7MSF6.mjs";
|
|
19
18
|
export {
|
|
20
19
|
AuthenticationError,
|
|
21
20
|
BoostedTravel,
|
|
@@ -26,7 +25,6 @@ export {
|
|
|
26
25
|
LetsFGError,
|
|
27
26
|
OfferExpiredError,
|
|
28
27
|
PaymentRequiredError,
|
|
29
|
-
StarRequiredError,
|
|
30
28
|
ValidationError,
|
|
31
29
|
cheapestOffer,
|
|
32
30
|
index_default as default,
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "letsfg",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "Agent-native flight search & booking.
|
|
3
|
+
"version": "1.7.0",
|
|
4
|
+
"description": "Agent-native flight search & booking. 200 airline connectors run locally + enterprise GDS/NDC APIs. Built for autonomous AI agents.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
7
7
|
"types": "dist/index.d.ts",
|