fortrip 0.3.0 → 0.3.1
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/AGENT_GUIDE.md +102 -35
- package/LICENSE +21 -0
- package/README.md +64 -19
- package/dist/cli.js +737 -127
- package/guides/planning.md +8 -5
- package/package.json +2 -2
- package/skills/fortrip-hotels/SKILL.md +0 -20
package/AGENT_GUIDE.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Fortrip
|
|
1
|
+
# Fortrip
|
|
2
2
|
|
|
3
3
|
Fortrip sells hotel rooms at supplier net prices. The
|
|
4
4
|
`fortrip` CLI (npm package `fortrip`) calls the Fortrip API as the
|
|
@@ -13,6 +13,9 @@ signed-in user and prints JSON.
|
|
|
13
13
|
the user pays in their browser).
|
|
14
14
|
|
|
15
15
|
Not for flights, activities, or changing/cancelling an existing booking.
|
|
16
|
+
For changes, cancellations, refunds or any other problem with a booking, the
|
|
17
|
+
user emails info@fortrip.ai with the booking's `orderUrl` (never
|
|
18
|
+
`paymentUrl` or `statusUrl`).
|
|
16
19
|
|
|
17
20
|
For flexible dates, a budget, split stays, several destinations or "find me
|
|
18
21
|
the best", also run `npx -y fortrip@latest skill planning` before searching.
|
|
@@ -20,7 +23,8 @@ the best", also run `npx -y fortrip@latest skill planning` before searching.
|
|
|
20
23
|
## Setup
|
|
21
24
|
|
|
22
25
|
Run every command as `npx -y fortrip@latest <command>`, the same version that
|
|
23
|
-
printed this guide. The examples below shorten that to `fortrip
|
|
26
|
+
printed this guide. The examples below shorten that to `fortrip`;
|
|
27
|
+
`fortrip <command> --help` lists a command's flags.
|
|
24
28
|
|
|
25
29
|
When the user first asks about hotels, run `fortrip whoami` before asking
|
|
26
30
|
follow-up questions, so a login can happen while they answer.
|
|
@@ -29,25 +33,35 @@ If a command exits with code **3** and stderr has `loginUrl`, show it to the
|
|
|
29
33
|
user as a link together with `userCode`, e.g. "Sign in to Fortrip: <loginUrl>
|
|
30
34
|
(code BCDF-GHJK) and tell me when you're done." When they confirm, rerun the
|
|
31
35
|
same command; it finishes the login itself. Don't run `fortrip login` — it
|
|
32
|
-
waits for up to 10 minutes.
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
36
|
+
waits for up to 10 minutes. Commands that exit 3 together share one
|
|
37
|
+
`loginUrl`; show it once. If the rerun gives a different `loginUrl`, show
|
|
38
|
+
that one.
|
|
39
|
+
|
|
40
|
+
When Fortrip doesn't accept the saved sign-in (it was revoked or has
|
|
41
|
+
expired, or Fortrip had a passing problem), the command also exits 3 with a
|
|
42
|
+
`loginUrl`; handle it the same way. The saved sign-in is kept until the
|
|
43
|
+
user approves the new link, so after a passing problem the next command
|
|
44
|
+
works without signing in again. Exit 3 with `tokenSource: "FORTRIP_TOKEN"` means Fortrip
|
|
45
|
+
didn't accept the token the user set in `FORTRIP_TOKEN`: retry once a
|
|
46
|
+
little later, and if it keeps happening, tell the user to replace or unset
|
|
47
|
+
it.
|
|
48
|
+
|
|
49
|
+
Sign-in happens only in the browser. In CI, the user can set `FORTRIP_TOKEN`
|
|
50
|
+
instead. Never ask the user to paste a token into the chat.
|
|
40
51
|
|
|
41
52
|
## Exit codes
|
|
42
53
|
|
|
43
54
|
| Code | Meaning | What to do |
|
|
44
55
|
|---|---|---|
|
|
45
56
|
| 0 | Success; JSON on stdout | Continue |
|
|
46
|
-
| 1 | Other error (supplier error, rate no longer bookable, network) | Read `error` on stderr; re-run `rates` if a rate went stale |
|
|
47
|
-
| 2 | Invalid arguments | Fix the flags; stderr `issues` lists
|
|
57
|
+
| 1 | Other error (supplier error, rate no longer bookable, network error or timeout) | Read `error` on stderr; if `retryable` is true (supplier unreachable or timed out, Fortrip briefly unavailable, or no response from Fortrip), wait `retryAfterSeconds` (or a few seconds) and retry once; re-run `rates` if a rate went stale. `book` errors carry a `reason` (below) |
|
|
58
|
+
| 2 | Invalid arguments | Fix the flags; stderr `issues` lists each bad field with a message |
|
|
48
59
|
| 3 | Not logged in | Show `loginUrl` to the user, then rerun (above) |
|
|
49
60
|
| 4 | Rate limited | Wait `retryAfterSeconds`, then retry once |
|
|
50
61
|
|
|
62
|
+
Output on stdout or stderr can carry `warning` (with `recoveryFile` when a
|
|
63
|
+
sign-in couldn't be saved): pass it on to the user.
|
|
64
|
+
|
|
51
65
|
## Recommended order
|
|
52
66
|
|
|
53
67
|
1. **Search** — find candidates and indicative prices:
|
|
@@ -63,7 +77,9 @@ token into the chat.
|
|
|
63
77
|
`--price-min` / `--price-max` are in that currency.
|
|
64
78
|
`--facility` names must match the catalogue exactly (e.g. `Swimming pool`,
|
|
65
79
|
`Parking`), otherwise nothing matches. Prices here (`price.nightlyFrom`,
|
|
66
|
-
`totalFrom`) are **indicative floors**, not quotes — say so.
|
|
80
|
+
`totalFrom`) are **indicative floors**, not quotes — say so. A search
|
|
81
|
+
that matches too many hotels fails with `matched` and `maxMatches`: narrow
|
|
82
|
+
it (a city, an area, stars or a price range).
|
|
67
83
|
|
|
68
84
|
2. **Hotel detail** (optional) — description, policies, facilities, photos:
|
|
69
85
|
|
|
@@ -79,13 +95,30 @@ token into the chat.
|
|
|
79
95
|
[--nationality CN] [--board BB] [--free-cancellation] [--currency USD]
|
|
80
96
|
```
|
|
81
97
|
|
|
98
|
+
`--adults` and `--child-age` are **per room**, and every room has the same
|
|
99
|
+
occupancy: 2 rooms for 4 adults is `--rooms 2 --adults 2`. If the party
|
|
100
|
+
doesn't divide evenly (3 adults in 2 rooms), ask the user whether to price
|
|
101
|
+
every room for the larger number or book the rooms separately. Limits:
|
|
102
|
+
1–8 rooms, 1–8 adults and 0–8 children (aged 0–17) per room, 1–15
|
|
103
|
+
nights, up to 15 hotels per call.
|
|
104
|
+
|
|
82
105
|
This call takes about 15 seconds. Prices are in the response's `currency`,
|
|
83
106
|
converted at Stripe's exchange rate (refreshed hourly), or a fixed fallback
|
|
84
107
|
rate when Stripe is unavailable; `fx` says which, and is `null` when
|
|
85
|
-
nothing needed converting. Present each option with
|
|
86
|
-
|
|
87
|
-
`
|
|
88
|
-
|
|
108
|
+
nothing needed converting. Present each option with:
|
|
109
|
+
|
|
110
|
+
- meal plan: `boardCode` (RO room only, BB breakfast, HB breakfast +
|
|
111
|
+
dinner, FB breakfast + lunch + dinner, BL lunch, BD dinner, HBBL
|
|
112
|
+
breakfast + lunch, HBLD lunch + dinner, AI all inclusive) together with
|
|
113
|
+
`boardCount`, how many guests per room the meal plan covers; fewer than
|
|
114
|
+
the adults per room means not everyone gets the meals (BB with
|
|
115
|
+
`boardCount` 1 for 2 adults is breakfast for 1 of 2), so say who is
|
|
116
|
+
covered;
|
|
117
|
+
- `freeCancelUntil` / `refundable`, `isInstantConfirm`, and any `fees`
|
|
118
|
+
(taxes paid at the hotel, in their own currency).
|
|
119
|
+
|
|
120
|
+
`--nationality` isn't sent with the booking: a rate restricted to that
|
|
121
|
+
nationality may change or be refused when booked.
|
|
89
122
|
|
|
90
123
|
4. **Book** — only after the user picks one rate and gives guest details:
|
|
91
124
|
|
|
@@ -97,37 +130,71 @@ token into the chat.
|
|
|
97
130
|
```
|
|
98
131
|
|
|
99
132
|
`--hotel`, `--room-id`, `--rate-plan`, dates, `--rooms`, `--adults` and
|
|
100
|
-
`--child-age` must be exactly the values used in `rates
|
|
101
|
-
be in Latin letters as on the
|
|
102
|
-
|
|
103
|
-
|
|
133
|
+
`--child-age` must be exactly the values used in `rates`; `book` requires
|
|
134
|
+
`--rooms` and `--adults`. Guest names must be in Latin letters as on the
|
|
135
|
+
passport ("First Last"; last word is the last name; `"First Last:2"` puts
|
|
136
|
+
the guest in room 2; 1–60 characters each). Each room needs at least one
|
|
137
|
+
guest. The contact name takes up to 120 characters, the phone 3–40.
|
|
138
|
+
`--special-requests` must be in English and isn't guaranteed. `book`
|
|
139
|
+
accepts only these fields: a `--body` with any other field (such as
|
|
140
|
+
`nationality`) is rejected with exit 2.
|
|
141
|
+
|
|
142
|
+
One booking covers at most 15 nights; book a longer stay as separate
|
|
143
|
+
bookings. `book` checks the rate with the supplier again and can take up
|
|
144
|
+
to about 2 minutes: allow the command at least 3 minutes, and if it times
|
|
145
|
+
out, run it again with identical flags. That is always safe: it returns
|
|
146
|
+
the same order, with the same or a refreshed payment link.
|
|
104
147
|
|
|
105
148
|
## Before giving the payment link
|
|
106
149
|
|
|
107
|
-
`book` returns `paymentUrl`, `amount`, `currency`, `terms`, `
|
|
108
|
-
`orderUrl`. Before you hand over `paymentUrl`:
|
|
109
|
-
|
|
110
|
-
1. **Show
|
|
111
|
-
(`
|
|
112
|
-
|
|
113
|
-
`
|
|
150
|
+
`book` returns `paymentUrl`, `amount`, `currency`, `terms`, `stay`,
|
|
151
|
+
`statusUrl` and `orderUrl`. Before you hand over `paymentUrl`:
|
|
152
|
+
|
|
153
|
+
1. **Show what will be booked and ask the user to confirm.** From `stay`:
|
|
154
|
+
hotel (`hotelName`), room (`roomName`), dates, nights, rooms and guests per
|
|
155
|
+
room (`adultsPerRoom`, `childrenAgesPerRoom`); if `stay` is missing, use
|
|
156
|
+
the values you passed. From `terms`: meal plan (`boardCode` with
|
|
157
|
+
`boardCount`), cancellation (`refundable`, `freeCancelUntil`, the
|
|
158
|
+
`cancellation` ladder), confirmation (`isInstantConfirm`, `confirmByMins`)
|
|
159
|
+
and `payAtHotelFees`. Then the `amount` and `currency`, and end your reply
|
|
160
|
+
by asking them to confirm. If `amount` or `terms` is `null`, say it
|
|
161
|
+
couldn't be read rather than guess; the payment page shows the amount.
|
|
114
162
|
2. **Explain the amount.** `rates` showed a converted figure, but the charge
|
|
115
163
|
is `amount` in `currency` (usually USD), and the Stripe page may display
|
|
116
164
|
the user's local currency at Stripe's rate. The `rates` figure used a
|
|
117
165
|
Stripe rate too, so it is usually close, but the amount on the payment page
|
|
118
166
|
is what will be charged; the `rates` figure was a reference.
|
|
119
|
-
3.
|
|
167
|
+
3. **Only after they confirm, give `paymentUrl` exactly as returned**: don't
|
|
168
|
+
shorten, rebuild or re-encode it. It opens a Fortrip page that recaps the
|
|
169
|
+
booking and continues to payment.
|
|
170
|
+
4. The link is for **this user only**: whoever has it can pay. Don't post it
|
|
120
171
|
in shared channels, logs or tickets. It expires after about 3 hours 45
|
|
121
172
|
minutes; call `book` again with the same details for a fresh one.
|
|
122
173
|
|
|
174
|
+
Never ask for, accept or pass on payment card details; payment happens only
|
|
175
|
+
on the payment page. A card number in a guest name, the contact name or the
|
|
176
|
+
special requests is rejected with exit 2.
|
|
177
|
+
|
|
123
178
|
After paying, the user lands on `statusUrl`, which shows confirmation progress
|
|
124
179
|
without signing in. `orderUrl` is the signed-in order page.
|
|
125
180
|
|
|
126
181
|
## Errors from `book`
|
|
127
182
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
- `
|
|
131
|
-
|
|
132
|
-
- `
|
|
133
|
-
|
|
183
|
+
Act on `reason` in stderr:
|
|
184
|
+
|
|
185
|
+
- `already_booked` (409, with `agentOrderId`): this exact stay is already paid
|
|
186
|
+
or completed — show `orderUrl`, don't book again.
|
|
187
|
+
- `price_or_terms_changed` (409, with `changes`): show what changed, re-run
|
|
188
|
+
`rates` and confirm again with the user.
|
|
189
|
+
- `rate_unavailable` (422): the rate can no longer be booked — re-run `rates`
|
|
190
|
+
and offer what is left.
|
|
191
|
+
- `supplier_unavailable` (503 or 504, `retryable: true`): wait
|
|
192
|
+
`retryAfterSeconds` and retry once with identical flags. A 503 with
|
|
193
|
+
`retryable: true` and no `reason` (a passing outage) is handled the same
|
|
194
|
+
way.
|
|
195
|
+
- `refused` (any other 422): the booking was refused (guest names, too many
|
|
196
|
+
attempts, bookings paused, or a preview deployment). Read `error`.
|
|
197
|
+
|
|
198
|
+
Older servers send no `reason`: there a 409 with `agentOrderId` is
|
|
199
|
+
`already_booked`, a 409 with `changes` is `price_or_terms_changed`, any other
|
|
200
|
+
409 is `rate_unavailable`, and a 422 is `refused`.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 FortripEngineering
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
# fortrip-cli
|
|
2
2
|
|
|
3
|
-
Search, price and book Fortrip hotels from the terminal or an AI agent.
|
|
3
|
+
Search, price and book Fortrip hotels from the terminal or an AI agent.
|
|
4
4
|
The npm package and the command are both `fortrip`.
|
|
5
5
|
|
|
6
|
+
For MCP clients, see the separately maintained
|
|
7
|
+
[Fortrip MCP](https://github.com/FortripEngineering/fortrip-mcp)
|
|
8
|
+
repository for local and hosted connection instructions.
|
|
9
|
+
|
|
6
10
|
```bash
|
|
7
11
|
npx fortrip login # sign in through the browser
|
|
8
12
|
npx fortrip search --query Bangkok --check-in 2026-11-10 --check-out 2026-11-12
|
|
@@ -20,52 +24,77 @@ Requires Node.js 22 or newer. No runtime dependencies.
|
|
|
20
24
|
| `search` | Hotels with indicative prices |
|
|
21
25
|
| `hotel <hotelId> [--with-rooms]` | Static hotel detail |
|
|
22
26
|
| `rates` | Live rooms and rates |
|
|
23
|
-
| `book` | Order +
|
|
27
|
+
| `book` | Order + payment link (a Fortrip page that continues to Stripe) |
|
|
28
|
+
|
|
29
|
+
Run `fortrip --help` for every flag, or `fortrip <command> --help` for one
|
|
30
|
+
command's. `search`, `rates` and `book` also accept `--body '<json>'` or
|
|
31
|
+
`--body @file.json` with the raw request body; flags override its fields.
|
|
24
32
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
33
|
+
`--adults` and `--child-age` are per room, and every room has the same
|
|
34
|
+
occupancy: 2 rooms for 4 adults is `--rooms 2 --adults 2`. `rates` defaults
|
|
35
|
+
to 1 room for 2 adults; `book` requires `--rooms` and `--adults`.
|
|
28
36
|
|
|
29
37
|
Output is JSON on stdout. Errors are JSON on stderr, with fixed exit codes:
|
|
30
38
|
|
|
31
39
|
| Code | Meaning |
|
|
32
40
|
|---|---|
|
|
33
41
|
| 0 | Success |
|
|
34
|
-
| 1 | Other error |
|
|
42
|
+
| 1 | Other error (`retryable: true` on stderr: worth one retry) |
|
|
35
43
|
| 2 | Invalid arguments (local or HTTP 400) |
|
|
36
|
-
| 3 | Not logged in
|
|
44
|
+
| 3 | Not logged in, or the sign-in wasn't accepted (HTTP 401) |
|
|
37
45
|
| 4 | Rate limited (HTTP 429; `retryAfterSeconds` on stderr) |
|
|
38
46
|
|
|
39
47
|
## Credentials
|
|
40
48
|
|
|
41
49
|
- `login` saves the token to `~/.config/fortrip/credentials.json`
|
|
42
|
-
(`$XDG_CONFIG_HOME` is honoured), mode `0600`.
|
|
43
|
-
so a token is only
|
|
50
|
+
(`$XDG_CONFIG_HOME` is honoured), mode `0600`. Saved tokens are stored per
|
|
51
|
+
API URL, so a saved token is only sent to the server that issued it.
|
|
44
52
|
- Without a token, any other command starts a device login and exits 3 with
|
|
45
53
|
`loginUrl` on stderr instead of waiting. Once that link is approved in the
|
|
46
54
|
browser, rerunning the command saves the token and carries on. This is how
|
|
47
|
-
AI agents sign in, since they can't sit in `login`.
|
|
48
|
-
|
|
55
|
+
AI agents sign in, since they can't sit in `login`. Commands run in
|
|
56
|
+
parallel share one login link. If the server doesn't accept the saved
|
|
57
|
+
token, the command keeps it and starts a new login the same way; once that
|
|
58
|
+
link is approved, the new token replaces the saved one.
|
|
59
|
+
- `FORTRIP_TOKEN` overrides the saved login (CI, remote sandboxes). It is not
|
|
60
|
+
tied to a server: it is sent to whatever `FORTRIP_API_URL` points at. If the
|
|
61
|
+
server doesn't accept it, commands exit 3 with `tokenSource: "FORTRIP_TOKEN"`
|
|
62
|
+
and no `loginUrl`.
|
|
49
63
|
- `FORTRIP_API_URL` overrides the base URL (default `https://fortrip.ai`).
|
|
50
64
|
Plain `http` is only accepted for `localhost`.
|
|
51
65
|
- `FORTRIP_CURRENCY` sets the default `--currency` for `search` and `rates`
|
|
52
66
|
(`CNY` or `USD`; the API defaults to `CNY`). Display only: `book`
|
|
53
67
|
charges the currency it returns.
|
|
54
68
|
|
|
55
|
-
|
|
69
|
+
`logout` revokes the saved token. With the Fortrip server update released
|
|
70
|
+
alongside CLI 0.3.1, sign-ins that go unused for 90 days stop working, and
|
|
71
|
+
signed-in users can list and revoke their CLI sign-ins in their Fortrip
|
|
72
|
+
account (account menu → **Fortrip CLI**).
|
|
73
|
+
|
|
74
|
+
If a new sign-in can't be saved (the file is busy or damaged), it is kept
|
|
75
|
+
in a `credentials.recovered-*.json` file next to `credentials.json` (mode
|
|
76
|
+
`0600`), and the command's JSON output names it in `warning` and
|
|
77
|
+
`recoveryFile`. The next successful save merges it back and removes the
|
|
78
|
+
file; `logout` revokes and removes these too.
|
|
79
|
+
|
|
80
|
+
Sharing `credentials.json` with 0.3.0 works on a best-effort basis: 0.3.0
|
|
81
|
+
finds the newest pending login where it expects it, but it writes the file
|
|
82
|
+
without a lock, so don't sign in with 0.3.0 and 0.3.1 at the same moment.
|
|
56
83
|
|
|
57
84
|
## Agent skill
|
|
58
85
|
|
|
59
86
|
```bash
|
|
60
|
-
npx skills add FortripEngineering/fortrip-cli
|
|
87
|
+
npx skills add FortripEngineering/fortrip-plugins --skill fortrip-cli
|
|
61
88
|
```
|
|
62
89
|
|
|
63
|
-
|
|
64
|
-
|
|
90
|
+
The skill lives in
|
|
91
|
+
[fortrip-plugins](https://github.com/FortripEngineering/fortrip-plugins); the
|
|
92
|
+
Claude directory plugin there uses the hosted MCP instead of the CLI. The
|
|
93
|
+
skill only tells the agent to run `npx -y fortrip@latest skill`, which prints
|
|
65
94
|
[`AGENT_GUIDE.md`](AGENT_GUIDE.md): when to use the CLI, the call order, login,
|
|
66
95
|
and what to show the user before handing over a payment link. The guide ships
|
|
67
96
|
with the package, so a CLI release updates every installed skill. Edit
|
|
68
|
-
`AGENT_GUIDE.md`, not
|
|
97
|
+
`AGENT_GUIDE.md`, not the skill.
|
|
69
98
|
|
|
70
99
|
`fortrip skill planning` prints [`guides/planning.md`](guides/planning.md):
|
|
71
100
|
what to ask, how to rank and how to present options for flexible dates,
|
|
@@ -73,6 +102,12 @@ budgets, split stays and several destinations. Both guides are printed with
|
|
|
73
102
|
`fortrip@latest` replaced by the running version, so an agent keeps using the
|
|
74
103
|
same CLI for the whole conversation.
|
|
75
104
|
|
|
105
|
+
## Support
|
|
106
|
+
|
|
107
|
+
For changes, cancellations, refunds or other help with a booking, email
|
|
108
|
+
[info@fortrip.ai](mailto:info@fortrip.ai) with the booking's order link
|
|
109
|
+
(`orderUrl`).
|
|
110
|
+
|
|
76
111
|
## Development
|
|
77
112
|
|
|
78
113
|
```bash
|
|
@@ -89,7 +124,9 @@ Point at a local Fortrip app with `FORTRIP_API_URL=http://localhost:3000`.
|
|
|
89
124
|
|
|
90
125
|
Pushing a `v*` tag publishes to npm through
|
|
91
126
|
[`.github/workflows/publish.yml`](.github/workflows/publish.yml), which signs
|
|
92
|
-
in with npm trusted publishing (no npm token in GitHub).
|
|
127
|
+
in with npm trusted publishing (no npm token in GitHub). Pull requests and
|
|
128
|
+
pushes to `main` run typecheck, tests and the build through
|
|
129
|
+
[`.github/workflows/ci.yml`](.github/workflows/ci.yml).
|
|
93
130
|
|
|
94
131
|
1. Bump the version in a PR and merge it into `main`:
|
|
95
132
|
`npm version minor --no-git-tag-version` (or `patch`).
|
|
@@ -101,5 +138,13 @@ in with npm trusted publishing (no npm token in GitHub).
|
|
|
101
138
|
```
|
|
102
139
|
|
|
103
140
|
The workflow refuses a tag that doesn't match `package.json` or isn't on
|
|
104
|
-
`main
|
|
105
|
-
|
|
141
|
+
`main`. A `build` job runs typecheck, tests and the build and packs the
|
|
142
|
+
tarball; a `publish` job in the `npm-publish` environment publishes that
|
|
143
|
+
tarball, with no install or build of its own. Every installed skill picks up
|
|
144
|
+
the new guide on its next `npx fortrip@latest skill`.
|
|
145
|
+
|
|
146
|
+
## License
|
|
147
|
+
|
|
148
|
+
The code and documentation in this repository are licensed under the
|
|
149
|
+
[MIT License](LICENSE). This license does not grant access to the hosted
|
|
150
|
+
Fortrip service, hotel inventory, or third-party data.
|