letsfg 1.2.0 → 1.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/README.md +13 -3
- package/dist/{chunk-R2DLDQIL.mjs → chunk-7LYR3CHE.mjs} +14 -2
- package/dist/cli.js +59 -38
- package/dist/cli.mjs +55 -39
- package/dist/index.d.mts +23 -4
- package/dist/index.d.ts +23 -4
- package/dist/index.js +15 -2
- package/dist/index.mjs +3 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,6 +1,13 @@
|
|
|
1
|
-
# LetsFG —
|
|
1
|
+
# LetsFG — Your AI agent just learned to book flights. (Node.js)
|
|
2
2
|
|
|
3
|
-
Search 400+ airlines at raw airline prices — **$50 cheaper** than Booking.com, Kayak, and other OTAs. Zero dependencies. Built for
|
|
3
|
+
**195 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
|
+
|
|
5
|
+
> **Don't want to install anything?** [**Try it on Messenger**](https://m.me/61579557368989) — search flights instantly, no setup needed.
|
|
6
|
+
|
|
7
|
+
[](https://github.com/LetsFG/LetsFG)
|
|
8
|
+
[](https://www.npmjs.com/package/letsfg)
|
|
9
|
+
|
|
10
|
+
> ⭐ **[Star the repo](https://github.com/LetsFG/LetsFG) → register → unlimited access forever.** First 1,000 stars only.
|
|
4
11
|
|
|
5
12
|
## Install
|
|
6
13
|
|
|
@@ -74,7 +81,7 @@ letsfg book off_xxx -p '{"id":"pas_xxx","given_name":"John",...}' -e john@exampl
|
|
|
74
81
|
|
|
75
82
|
### `searchLocal(origin, destination, dateFrom, options?)`
|
|
76
83
|
|
|
77
|
-
Search
|
|
84
|
+
Search 195 airline connectors locally (no API key needed). Requires Python + `letsfg` installed.
|
|
78
85
|
|
|
79
86
|
```typescript
|
|
80
87
|
import { searchLocal } from 'letsfg';
|
|
@@ -118,8 +125,11 @@ Or set the `LETSFG_MAX_BROWSERS` environment variable globally.
|
|
|
118
125
|
|
|
119
126
|
- **MCP Server**: `npx letsfg-mcp` — [npm](https://www.npmjs.com/package/letsfg-mcp)
|
|
120
127
|
- **Python SDK + CLI**: `pip install letsfg` — [PyPI](https://pypi.org/project/letsfg/)
|
|
128
|
+
- **Try without installing**: [Message us on Messenger](https://m.me/61579557368989)
|
|
121
129
|
- **GitHub**: [LetsFG/LetsFG](https://github.com/LetsFG/LetsFG)
|
|
122
130
|
|
|
131
|
+
> ⭐ **[Star the repo](https://github.com/LetsFG/LetsFG)** to unlock free access. First 1,000 stars only.
|
|
132
|
+
|
|
123
133
|
## License
|
|
124
134
|
|
|
125
135
|
MIT
|
|
@@ -106,6 +106,12 @@ 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
|
+
};
|
|
109
115
|
function routeStr(route) {
|
|
110
116
|
if (!route.segments.length) return "";
|
|
111
117
|
const codes = [route.segments[0].origin, ...route.segments.map((s) => s.destination)];
|
|
@@ -156,8 +162,13 @@ async function searchLocal(origin, destination, dateFrom, options = {}) {
|
|
|
156
162
|
child.on("close", (code) => {
|
|
157
163
|
try {
|
|
158
164
|
const data = JSON.parse(stdout);
|
|
159
|
-
if (data.error)
|
|
160
|
-
|
|
165
|
+
if (data.error) {
|
|
166
|
+
if (data.error.includes("GitHub star required") || data.error.includes("star required")) {
|
|
167
|
+
reject(new StarRequiredError(data.error));
|
|
168
|
+
} else {
|
|
169
|
+
reject(new LetsFGError(data.error));
|
|
170
|
+
}
|
|
171
|
+
} else resolve(data);
|
|
161
172
|
} catch {
|
|
162
173
|
reject(new LetsFGError(
|
|
163
174
|
`Python search failed (code ${code}): ${stdout || stderr}
|
|
@@ -459,6 +470,7 @@ export {
|
|
|
459
470
|
PaymentRequiredError,
|
|
460
471
|
OfferExpiredError,
|
|
461
472
|
ValidationError,
|
|
473
|
+
StarRequiredError,
|
|
462
474
|
offerSummary,
|
|
463
475
|
cheapestOffer,
|
|
464
476
|
searchLocal,
|
package/dist/cli.js
CHANGED
|
@@ -131,6 +131,12 @@ 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
|
+
};
|
|
134
140
|
function routeStr(route) {
|
|
135
141
|
if (!route.segments.length) return "";
|
|
136
142
|
const codes = [route.segments[0].origin, ...route.segments.map((s) => s.destination)];
|
|
@@ -604,42 +610,44 @@ async function cmdRegister(args) {
|
|
|
604
610
|
}
|
|
605
611
|
async function cmdStar(args) {
|
|
606
612
|
const jsonOut = hasFlag(args, "--json") || hasFlag(args, "-j");
|
|
607
|
-
const apiKey = getFlag(args, "--api-key", "-k");
|
|
608
|
-
const baseUrl = getFlag(args, "--base-url");
|
|
609
613
|
const github = getFlag(args, "--github", "-g");
|
|
610
614
|
if (!github) {
|
|
611
615
|
console.error("Usage: letsfg star --github <your-github-username>");
|
|
612
616
|
process.exit(1);
|
|
613
617
|
}
|
|
614
|
-
const
|
|
615
|
-
const
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
618
|
+
const { spawn } = await import("child_process");
|
|
619
|
+
const pythonCmd = process.platform === "win32" ? "python" : "python3";
|
|
620
|
+
return new Promise((resolve, reject) => {
|
|
621
|
+
const child = spawn(pythonCmd, ["-m", "letsfg.cli", "star", "--github", github], {
|
|
622
|
+
stdio: ["inherit", "pipe", "pipe"]
|
|
623
|
+
});
|
|
624
|
+
let stdout = "";
|
|
625
|
+
let stderr = "";
|
|
626
|
+
child.stdout.on("data", (d) => {
|
|
627
|
+
stdout += d.toString();
|
|
628
|
+
});
|
|
629
|
+
child.stderr.on("data", (d) => {
|
|
630
|
+
stderr += d.toString();
|
|
631
|
+
});
|
|
632
|
+
child.on("close", (code) => {
|
|
633
|
+
if (jsonOut) {
|
|
634
|
+
const verified = code === 0;
|
|
635
|
+
console.log(JSON.stringify({ status: verified ? "verified" : "star_required", github_username: github }));
|
|
636
|
+
} else {
|
|
637
|
+
if (stdout) console.log(stdout);
|
|
638
|
+
if (stderr && code !== 0) console.error(stderr);
|
|
639
|
+
}
|
|
640
|
+
if (code !== 0) {
|
|
641
|
+
process.exit(1);
|
|
642
|
+
}
|
|
643
|
+
resolve();
|
|
644
|
+
});
|
|
645
|
+
child.on("error", (err) => {
|
|
646
|
+
console.error(`Cannot start Python: ${err.message}`);
|
|
647
|
+
console.error("Install: pip install letsfg");
|
|
648
|
+
process.exit(1);
|
|
649
|
+
});
|
|
650
|
+
});
|
|
643
651
|
}
|
|
644
652
|
async function cmdSetupPayment(args) {
|
|
645
653
|
const jsonOut = hasFlag(args, "--json") || hasFlag(args, "-j");
|
|
@@ -697,16 +705,19 @@ var HELP = `
|
|
|
697
705
|
LetsFG \u2014 Agent-native flight search & booking.
|
|
698
706
|
|
|
699
707
|
Search 400+ airlines at raw airline prices \u2014 $20-50 cheaper than OTAs.
|
|
700
|
-
|
|
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>
|
|
701
713
|
|
|
702
714
|
Commands:
|
|
703
|
-
|
|
715
|
+
star --github <username> Verify GitHub star (required first!)
|
|
716
|
+
search <origin> <dest> <date> Search for flights (FREE with star)
|
|
704
717
|
locations <query> Resolve city name to IATA codes
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
book <offer_id> --passenger ... Book flight (FREE after unlock)
|
|
718
|
+
unlock <offer_id> Unlock offer (hosted mode only)
|
|
719
|
+
book <offer_id> --passenger ... Book flight
|
|
708
720
|
register --name ... --email ... Register new agent
|
|
709
|
-
setup-payment Legacy payment setup
|
|
710
721
|
me Show agent profile
|
|
711
722
|
|
|
712
723
|
Options:
|
|
@@ -715,7 +726,6 @@ Options:
|
|
|
715
726
|
--base-url API URL (default: https://api.letsfg.co)
|
|
716
727
|
|
|
717
728
|
Examples:
|
|
718
|
-
letsfg register --name my-agent --email me@example.com
|
|
719
729
|
letsfg star --github octocat
|
|
720
730
|
letsfg search GDN BER 2026-03-03 --sort price
|
|
721
731
|
letsfg unlock off_xxx
|
|
@@ -762,6 +772,17 @@ async function main() {
|
|
|
762
772
|
process.exit(1);
|
|
763
773
|
}
|
|
764
774
|
} 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
|
+
}
|
|
765
786
|
if (e instanceof LetsFGError) {
|
|
766
787
|
console.error(`Error: ${e.message}`);
|
|
767
788
|
process.exit(1);
|
package/dist/cli.mjs
CHANGED
|
@@ -2,8 +2,9 @@
|
|
|
2
2
|
import {
|
|
3
3
|
LetsFG,
|
|
4
4
|
LetsFGError,
|
|
5
|
+
StarRequiredError,
|
|
5
6
|
offerSummary
|
|
6
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-7LYR3CHE.mjs";
|
|
7
8
|
|
|
8
9
|
// src/cli.ts
|
|
9
10
|
function getFlag(args, flag, alias) {
|
|
@@ -225,42 +226,44 @@ async function cmdRegister(args) {
|
|
|
225
226
|
}
|
|
226
227
|
async function cmdStar(args) {
|
|
227
228
|
const jsonOut = hasFlag(args, "--json") || hasFlag(args, "-j");
|
|
228
|
-
const apiKey = getFlag(args, "--api-key", "-k");
|
|
229
|
-
const baseUrl = getFlag(args, "--base-url");
|
|
230
229
|
const github = getFlag(args, "--github", "-g");
|
|
231
230
|
if (!github) {
|
|
232
231
|
console.error("Usage: letsfg star --github <your-github-username>");
|
|
233
232
|
process.exit(1);
|
|
234
233
|
}
|
|
235
|
-
const
|
|
236
|
-
const
|
|
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
|
-
|
|
234
|
+
const { spawn } = await import("child_process");
|
|
235
|
+
const pythonCmd = process.platform === "win32" ? "python" : "python3";
|
|
236
|
+
return new Promise((resolve, reject) => {
|
|
237
|
+
const child = spawn(pythonCmd, ["-m", "letsfg.cli", "star", "--github", github], {
|
|
238
|
+
stdio: ["inherit", "pipe", "pipe"]
|
|
239
|
+
});
|
|
240
|
+
let stdout = "";
|
|
241
|
+
let stderr = "";
|
|
242
|
+
child.stdout.on("data", (d) => {
|
|
243
|
+
stdout += d.toString();
|
|
244
|
+
});
|
|
245
|
+
child.stderr.on("data", (d) => {
|
|
246
|
+
stderr += d.toString();
|
|
247
|
+
});
|
|
248
|
+
child.on("close", (code) => {
|
|
249
|
+
if (jsonOut) {
|
|
250
|
+
const verified = code === 0;
|
|
251
|
+
console.log(JSON.stringify({ status: verified ? "verified" : "star_required", github_username: github }));
|
|
252
|
+
} else {
|
|
253
|
+
if (stdout) console.log(stdout);
|
|
254
|
+
if (stderr && code !== 0) console.error(stderr);
|
|
255
|
+
}
|
|
256
|
+
if (code !== 0) {
|
|
257
|
+
process.exit(1);
|
|
258
|
+
}
|
|
259
|
+
resolve();
|
|
260
|
+
});
|
|
261
|
+
child.on("error", (err) => {
|
|
262
|
+
console.error(`Cannot start Python: ${err.message}`);
|
|
263
|
+
console.error("Install: pip install letsfg");
|
|
264
|
+
process.exit(1);
|
|
265
|
+
});
|
|
266
|
+
});
|
|
264
267
|
}
|
|
265
268
|
async function cmdSetupPayment(args) {
|
|
266
269
|
const jsonOut = hasFlag(args, "--json") || hasFlag(args, "-j");
|
|
@@ -318,16 +321,19 @@ var HELP = `
|
|
|
318
321
|
LetsFG \u2014 Agent-native flight search & booking.
|
|
319
322
|
|
|
320
323
|
Search 400+ airlines at raw airline prices \u2014 $20-50 cheaper than OTAs.
|
|
321
|
-
|
|
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>
|
|
322
329
|
|
|
323
330
|
Commands:
|
|
324
|
-
|
|
331
|
+
star --github <username> Verify GitHub star (required first!)
|
|
332
|
+
search <origin> <dest> <date> Search for flights (FREE with star)
|
|
325
333
|
locations <query> Resolve city name to IATA codes
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
book <offer_id> --passenger ... Book flight (FREE after unlock)
|
|
334
|
+
unlock <offer_id> Unlock offer (hosted mode only)
|
|
335
|
+
book <offer_id> --passenger ... Book flight
|
|
329
336
|
register --name ... --email ... Register new agent
|
|
330
|
-
setup-payment Legacy payment setup
|
|
331
337
|
me Show agent profile
|
|
332
338
|
|
|
333
339
|
Options:
|
|
@@ -336,7 +342,6 @@ Options:
|
|
|
336
342
|
--base-url API URL (default: https://api.letsfg.co)
|
|
337
343
|
|
|
338
344
|
Examples:
|
|
339
|
-
letsfg register --name my-agent --email me@example.com
|
|
340
345
|
letsfg star --github octocat
|
|
341
346
|
letsfg search GDN BER 2026-03-03 --sort price
|
|
342
347
|
letsfg unlock off_xxx
|
|
@@ -383,6 +388,17 @@ async function main() {
|
|
|
383
388
|
process.exit(1);
|
|
384
389
|
}
|
|
385
390
|
} 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
|
+
}
|
|
386
402
|
if (e instanceof LetsFGError) {
|
|
387
403
|
console.error(`Error: ${e.message}`);
|
|
388
404
|
process.exit(1);
|
package/dist/index.d.mts
CHANGED
|
@@ -1,14 +1,19 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* LetsFG — Agent-native flight search & booking SDK for Node.js/TypeScript.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* 195 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
|
+
*
|
|
7
12
|
* @example
|
|
8
13
|
* ```ts
|
|
9
14
|
* import { LetsFG, searchLocal } from 'letsfg';
|
|
10
15
|
*
|
|
11
|
-
* // Local search — FREE
|
|
16
|
+
* // Local search — FREE with GitHub star
|
|
12
17
|
* const local = await searchLocal('SHA', 'CTU', '2026-03-20');
|
|
13
18
|
*
|
|
14
19
|
* // Full API — search + unlock + book
|
|
@@ -183,12 +188,25 @@ declare class OfferExpiredError extends LetsFGError {
|
|
|
183
188
|
declare class ValidationError extends LetsFGError {
|
|
184
189
|
constructor(message: string, statusCode?: number, response?: Record<string, unknown>, errorCode?: string);
|
|
185
190
|
}
|
|
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
|
+
}
|
|
186
199
|
/** One-line offer summary */
|
|
187
200
|
declare function offerSummary(offer: FlightOffer): string;
|
|
188
201
|
/** Get cheapest offer from search results */
|
|
189
202
|
declare function cheapestOffer(result: FlightSearchResult): FlightOffer | null;
|
|
190
203
|
/**
|
|
191
|
-
* Search flights using
|
|
204
|
+
* Search flights using 195 local airline connectors — FREE with GitHub star!
|
|
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>
|
|
192
210
|
*
|
|
193
211
|
* Requires: pip install letsfg && playwright install chromium
|
|
194
212
|
*
|
|
@@ -196,6 +214,7 @@ declare function cheapestOffer(result: FlightSearchResult): FlightOffer | null;
|
|
|
196
214
|
* @param destination - IATA code (e.g., "CTU")
|
|
197
215
|
* @param dateFrom - Departure date "YYYY-MM-DD"
|
|
198
216
|
* @param options - Optional: currency, adults, limit, etc.
|
|
217
|
+
* @throws {StarRequiredError} If GitHub star not verified
|
|
199
218
|
*/
|
|
200
219
|
declare function searchLocal(origin: string, destination: string, dateFrom: string, options?: Partial<SearchOptions>): Promise<FlightSearchResult>;
|
|
201
220
|
declare class LetsFG {
|
|
@@ -282,4 +301,4 @@ declare const BoostedTravel: typeof LetsFG;
|
|
|
282
301
|
declare const BoostedTravelError: typeof LetsFGError;
|
|
283
302
|
type BoostedTravelConfig = LetsFGConfig;
|
|
284
303
|
|
|
285
|
-
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 };
|
|
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, StarRequiredError, type UnlockResult, ValidationError, cheapestOffer, LetsFG as default, systemInfo as getSystemInfo, searchLocal as localSearch, offerSummary, searchLocal, systemInfo };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,14 +1,19 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* LetsFG — Agent-native flight search & booking SDK for Node.js/TypeScript.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* 195 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
|
+
*
|
|
7
12
|
* @example
|
|
8
13
|
* ```ts
|
|
9
14
|
* import { LetsFG, searchLocal } from 'letsfg';
|
|
10
15
|
*
|
|
11
|
-
* // Local search — FREE
|
|
16
|
+
* // Local search — FREE with GitHub star
|
|
12
17
|
* const local = await searchLocal('SHA', 'CTU', '2026-03-20');
|
|
13
18
|
*
|
|
14
19
|
* // Full API — search + unlock + book
|
|
@@ -183,12 +188,25 @@ declare class OfferExpiredError extends LetsFGError {
|
|
|
183
188
|
declare class ValidationError extends LetsFGError {
|
|
184
189
|
constructor(message: string, statusCode?: number, response?: Record<string, unknown>, errorCode?: string);
|
|
185
190
|
}
|
|
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
|
+
}
|
|
186
199
|
/** One-line offer summary */
|
|
187
200
|
declare function offerSummary(offer: FlightOffer): string;
|
|
188
201
|
/** Get cheapest offer from search results */
|
|
189
202
|
declare function cheapestOffer(result: FlightSearchResult): FlightOffer | null;
|
|
190
203
|
/**
|
|
191
|
-
* Search flights using
|
|
204
|
+
* Search flights using 195 local airline connectors — FREE with GitHub star!
|
|
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>
|
|
192
210
|
*
|
|
193
211
|
* Requires: pip install letsfg && playwright install chromium
|
|
194
212
|
*
|
|
@@ -196,6 +214,7 @@ declare function cheapestOffer(result: FlightSearchResult): FlightOffer | null;
|
|
|
196
214
|
* @param destination - IATA code (e.g., "CTU")
|
|
197
215
|
* @param dateFrom - Departure date "YYYY-MM-DD"
|
|
198
216
|
* @param options - Optional: currency, adults, limit, etc.
|
|
217
|
+
* @throws {StarRequiredError} If GitHub star not verified
|
|
199
218
|
*/
|
|
200
219
|
declare function searchLocal(origin: string, destination: string, dateFrom: string, options?: Partial<SearchOptions>): Promise<FlightSearchResult>;
|
|
201
220
|
declare class LetsFG {
|
|
@@ -282,4 +301,4 @@ declare const BoostedTravel: typeof LetsFG;
|
|
|
282
301
|
declare const BoostedTravelError: typeof LetsFGError;
|
|
283
302
|
type BoostedTravelConfig = LetsFGConfig;
|
|
284
303
|
|
|
285
|
-
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 };
|
|
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, StarRequiredError, type UnlockResult, ValidationError, cheapestOffer, LetsFG as default, systemInfo as getSystemInfo, searchLocal as localSearch, offerSummary, searchLocal, systemInfo };
|
package/dist/index.js
CHANGED
|
@@ -39,6 +39,7 @@ __export(index_exports, {
|
|
|
39
39
|
LetsFGError: () => LetsFGError,
|
|
40
40
|
OfferExpiredError: () => OfferExpiredError,
|
|
41
41
|
PaymentRequiredError: () => PaymentRequiredError,
|
|
42
|
+
StarRequiredError: () => StarRequiredError,
|
|
42
43
|
ValidationError: () => ValidationError,
|
|
43
44
|
cheapestOffer: () => cheapestOffer,
|
|
44
45
|
default: () => index_default,
|
|
@@ -156,6 +157,12 @@ var ValidationError = class extends LetsFGError {
|
|
|
156
157
|
this.name = "ValidationError";
|
|
157
158
|
}
|
|
158
159
|
};
|
|
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
|
+
};
|
|
159
166
|
function routeStr(route) {
|
|
160
167
|
if (!route.segments.length) return "";
|
|
161
168
|
const codes = [route.segments[0].origin, ...route.segments.map((s) => s.destination)];
|
|
@@ -206,8 +213,13 @@ async function searchLocal(origin, destination, dateFrom, options = {}) {
|
|
|
206
213
|
child.on("close", (code) => {
|
|
207
214
|
try {
|
|
208
215
|
const data = JSON.parse(stdout);
|
|
209
|
-
if (data.error)
|
|
210
|
-
|
|
216
|
+
if (data.error) {
|
|
217
|
+
if (data.error.includes("GitHub star required") || data.error.includes("star required")) {
|
|
218
|
+
reject(new StarRequiredError(data.error));
|
|
219
|
+
} else {
|
|
220
|
+
reject(new LetsFGError(data.error));
|
|
221
|
+
}
|
|
222
|
+
} else resolve(data);
|
|
211
223
|
} catch {
|
|
212
224
|
reject(new LetsFGError(
|
|
213
225
|
`Python search failed (code ${code}): ${stdout || stderr}
|
|
@@ -511,6 +523,7 @@ var BoostedTravelError = LetsFGError;
|
|
|
511
523
|
LetsFGError,
|
|
512
524
|
OfferExpiredError,
|
|
513
525
|
PaymentRequiredError,
|
|
526
|
+
StarRequiredError,
|
|
514
527
|
ValidationError,
|
|
515
528
|
cheapestOffer,
|
|
516
529
|
getSystemInfo,
|
package/dist/index.mjs
CHANGED
|
@@ -8,13 +8,14 @@ import {
|
|
|
8
8
|
LetsFGError,
|
|
9
9
|
OfferExpiredError,
|
|
10
10
|
PaymentRequiredError,
|
|
11
|
+
StarRequiredError,
|
|
11
12
|
ValidationError,
|
|
12
13
|
cheapestOffer,
|
|
13
14
|
index_default,
|
|
14
15
|
offerSummary,
|
|
15
16
|
searchLocal,
|
|
16
17
|
systemInfo
|
|
17
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-7LYR3CHE.mjs";
|
|
18
19
|
export {
|
|
19
20
|
AuthenticationError,
|
|
20
21
|
BoostedTravel,
|
|
@@ -25,6 +26,7 @@ export {
|
|
|
25
26
|
LetsFGError,
|
|
26
27
|
OfferExpiredError,
|
|
27
28
|
PaymentRequiredError,
|
|
29
|
+
StarRequiredError,
|
|
28
30
|
ValidationError,
|
|
29
31
|
cheapestOffer,
|
|
30
32
|
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.4.0",
|
|
4
|
+
"description": "Agent-native flight search & booking. 195 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",
|