cookunity-mcp-server 1.0.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/LICENSE +21 -0
- package/README.md +113 -0
- package/dist/constants.d.ts +13 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +14 -0
- package/dist/constants.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +79 -0
- package/dist/index.js.map +1 -0
- package/dist/schemas/index.d.ts +215 -0
- package/dist/schemas/index.d.ts.map +1 -0
- package/dist/schemas/index.js +84 -0
- package/dist/schemas/index.js.map +1 -0
- package/dist/services/api.d.ts +35 -0
- package/dist/services/api.d.ts.map +1 -0
- package/dist/services/api.js +249 -0
- package/dist/services/api.js.map +1 -0
- package/dist/services/auth.d.ts +14 -0
- package/dist/services/auth.d.ts.map +1 -0
- package/dist/services/auth.js +96 -0
- package/dist/services/auth.js.map +1 -0
- package/dist/services/helpers.d.ts +23 -0
- package/dist/services/helpers.d.ts.map +1 -0
- package/dist/services/helpers.js +94 -0
- package/dist/services/helpers.js.map +1 -0
- package/dist/tools/cart.d.ts +4 -0
- package/dist/tools/cart.d.ts.map +1 -0
- package/dist/tools/cart.js +186 -0
- package/dist/tools/cart.js.map +1 -0
- package/dist/tools/deliveries.d.ts +4 -0
- package/dist/tools/deliveries.d.ts.map +1 -0
- package/dist/tools/deliveries.js +190 -0
- package/dist/tools/deliveries.js.map +1 -0
- package/dist/tools/menu.d.ts +4 -0
- package/dist/tools/menu.d.ts.map +1 -0
- package/dist/tools/menu.js +293 -0
- package/dist/tools/menu.js.map +1 -0
- package/dist/tools/pricing.d.ts +4 -0
- package/dist/tools/pricing.d.ts.map +1 -0
- package/dist/tools/pricing.js +116 -0
- package/dist/tools/pricing.js.map +1 -0
- package/dist/tools/user.d.ts +4 -0
- package/dist/tools/user.d.ts.map +1 -0
- package/dist/tools/user.js +97 -0
- package/dist/tools/user.js.map +1 -0
- package/dist/types.d.ts +228 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +51 -0
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
import axios, { AxiosError } from "axios";
|
|
2
|
+
import { CookUnityAuth } from "./auth.js";
|
|
3
|
+
import { MENU_SERVICE_URL, SUBSCRIPTION_URL } from "../constants.js";
|
|
4
|
+
export class CookUnityAPI {
|
|
5
|
+
auth;
|
|
6
|
+
constructor(email, password) {
|
|
7
|
+
this.auth = new CookUnityAuth(email, password);
|
|
8
|
+
}
|
|
9
|
+
async getMenu(date, filters = {}) {
|
|
10
|
+
const query = `
|
|
11
|
+
query getMenu($date: String!, $filters: MenuFilters!) {
|
|
12
|
+
menu(date: $date, filters: $filters) {
|
|
13
|
+
categories { id title subtitle label tag }
|
|
14
|
+
meals {
|
|
15
|
+
id batchId name shortDescription image imagePath price finalPrice premiumFee
|
|
16
|
+
sku stock isNewMeal userRating inventoryId categoryId
|
|
17
|
+
searchBy { cuisines chefFirstName chefLastName dietTags ingredients proteinTags }
|
|
18
|
+
nutritionalFacts { calories fat carbs sodium fiber }
|
|
19
|
+
chef { id firstName lastName }
|
|
20
|
+
meatType category { id title label }
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
`;
|
|
25
|
+
const data = await this.queryMenu(query, { date, filters });
|
|
26
|
+
return data.menu;
|
|
27
|
+
}
|
|
28
|
+
async getMenuDetailed(date) {
|
|
29
|
+
const query = `
|
|
30
|
+
query getMenu($date: String!, $filters: MenuFilters!) {
|
|
31
|
+
menu(date: $date, filters: $filters) {
|
|
32
|
+
meals {
|
|
33
|
+
id batchId name shortDescription image imagePath price finalPrice premiumFee
|
|
34
|
+
sku stock isNewMeal userRating inventoryId categoryId
|
|
35
|
+
searchBy { cuisines chefFirstName chefLastName dietTags ingredients proteinTags }
|
|
36
|
+
nutritionalFacts { calories fat carbs sodium fiber protein sugar }
|
|
37
|
+
chef { id firstName lastName }
|
|
38
|
+
meatType category { id title label }
|
|
39
|
+
allergens { name }
|
|
40
|
+
ingredients { name }
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
`;
|
|
45
|
+
const data = await this.queryMenu(query, { date, filters: {} });
|
|
46
|
+
return data.menu.meals;
|
|
47
|
+
}
|
|
48
|
+
async getUserInfo() {
|
|
49
|
+
const query = `
|
|
50
|
+
query {
|
|
51
|
+
users {
|
|
52
|
+
id name email plan_id store_id status
|
|
53
|
+
deliveryDays { id day time_start time_end }
|
|
54
|
+
currentCredit
|
|
55
|
+
ring { id name is_local }
|
|
56
|
+
addresses { id isActive city region postcode street }
|
|
57
|
+
profiles { id firstname lastname }
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
`;
|
|
61
|
+
const data = await this.querySubscription(query);
|
|
62
|
+
return data.users[0];
|
|
63
|
+
}
|
|
64
|
+
async getAllOrders() {
|
|
65
|
+
const data = await this.querySubscription(`query { allOrders { id deliveryDate } }`);
|
|
66
|
+
return data.allOrders;
|
|
67
|
+
}
|
|
68
|
+
async getUpcomingDays() {
|
|
69
|
+
const query = `
|
|
70
|
+
query {
|
|
71
|
+
upcomingDays {
|
|
72
|
+
id date displayDate available menuAvailable canEdit skip isPaused
|
|
73
|
+
cutoff { time userTimeZone }
|
|
74
|
+
cart {
|
|
75
|
+
product {
|
|
76
|
+
id inventoryId name sku image_path price_incl_tax realPrice
|
|
77
|
+
chef_firstname chef_lastname meat_type premium_special
|
|
78
|
+
}
|
|
79
|
+
qty
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
`;
|
|
84
|
+
const data = await this.querySubscription(query);
|
|
85
|
+
return data.upcomingDays;
|
|
86
|
+
}
|
|
87
|
+
async addMeal(date, inventoryId, quantity = 1, batchId) {
|
|
88
|
+
const mutation = `
|
|
89
|
+
mutation addMeal($date: String!, $batch_id: Int, $quantity: Int!, $inventory_id: String) {
|
|
90
|
+
addMeal(date: $date, batch_id: $batch_id, quantity: $quantity, inventory_id: $inventory_id) {
|
|
91
|
+
qty: quantity
|
|
92
|
+
inventoryId
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
`;
|
|
96
|
+
const data = await this.querySubscription(mutation, {
|
|
97
|
+
date,
|
|
98
|
+
batch_id: batchId,
|
|
99
|
+
quantity,
|
|
100
|
+
inventory_id: inventoryId,
|
|
101
|
+
});
|
|
102
|
+
return data.addMeal;
|
|
103
|
+
}
|
|
104
|
+
async removeMeal(date, inventoryId, quantity = 1) {
|
|
105
|
+
const mutation = `
|
|
106
|
+
mutation removeProductFromCart($date: String!, $quantity: Int!, $inventory_id: String) {
|
|
107
|
+
deleteMeal(date: $date, quantity: $quantity, inventory_id: $inventory_id) {
|
|
108
|
+
qty: quantity
|
|
109
|
+
inventoryId
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
`;
|
|
113
|
+
const data = await this.querySubscription(mutation, { date, quantity, inventory_id: inventoryId });
|
|
114
|
+
return data.deleteMeal;
|
|
115
|
+
}
|
|
116
|
+
async clearCart(date) {
|
|
117
|
+
await this.querySubscription(`mutation deleteCart($date: String!) { deleteCart(date: $date) }`, { date });
|
|
118
|
+
return true;
|
|
119
|
+
}
|
|
120
|
+
async skipDelivery(date) {
|
|
121
|
+
const mutation = `
|
|
122
|
+
mutation createSkip($skip: SkipInput!, $origin: OperationOrigin) {
|
|
123
|
+
createSkip(skip: $skip, origin: $origin) {
|
|
124
|
+
__typename
|
|
125
|
+
... on Skip { id }
|
|
126
|
+
... on OrderCreationError { error }
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
`;
|
|
130
|
+
const data = await this.querySubscription(mutation, {
|
|
131
|
+
skip: { date, deliveryDate: date },
|
|
132
|
+
origin: "WEB",
|
|
133
|
+
});
|
|
134
|
+
return data.createSkip;
|
|
135
|
+
}
|
|
136
|
+
async unskipDelivery(date) {
|
|
137
|
+
const mutation = `
|
|
138
|
+
mutation createUnskip($unskip: SkipInput!, $origin: OperationOrigin) {
|
|
139
|
+
createUnskip(unskip: $unskip, origin: $origin) {
|
|
140
|
+
__typename
|
|
141
|
+
... on Skip { id }
|
|
142
|
+
... on OrderCreationError { error }
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
`;
|
|
146
|
+
const data = await this.querySubscription(mutation, {
|
|
147
|
+
unskip: { date, deliveryDate: date },
|
|
148
|
+
origin: "WEB",
|
|
149
|
+
});
|
|
150
|
+
return data.createUnskip;
|
|
151
|
+
}
|
|
152
|
+
async createOrder(deliveryDate, start, end, products, options) {
|
|
153
|
+
const mutation = `
|
|
154
|
+
mutation createOrder($order: CreateOrderInput!) {
|
|
155
|
+
createOrder(order: $order) {
|
|
156
|
+
__typename
|
|
157
|
+
... on OrderCreation { id deliveryDate paymentStatus }
|
|
158
|
+
... on OrderCreationError { error outOfStockIds }
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
`;
|
|
162
|
+
const order = {
|
|
163
|
+
deliveryDate,
|
|
164
|
+
start,
|
|
165
|
+
end,
|
|
166
|
+
products: products.map((p) => ({ qty: p.qty, inventoryId: p.inventoryId })),
|
|
167
|
+
};
|
|
168
|
+
if (options?.comment)
|
|
169
|
+
order.comment = options.comment;
|
|
170
|
+
if (options?.tip != null)
|
|
171
|
+
order.tip = options.tip;
|
|
172
|
+
const data = await this.querySubscription(mutation, { order });
|
|
173
|
+
return data.createOrder;
|
|
174
|
+
}
|
|
175
|
+
async getPriceBreakdown(date, meals) {
|
|
176
|
+
const query = `
|
|
177
|
+
query getOrderDetail($date: String!, $cartId: String, $meals: [MealInput]) {
|
|
178
|
+
getOrderDetail(date: $date, cartId: $cartId, meals: $meals) {
|
|
179
|
+
qtyPlanMeals qtyItems totalPlanPrice totalExtraMeals totalTaxes
|
|
180
|
+
totalDeliveryFee totalExpressFee totalFee subTotalOrder
|
|
181
|
+
totalPromoDiscount totalOrder availableCredits totalOrderWithCreditsSubtracted
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
`;
|
|
185
|
+
const data = await this.querySubscription(query, { date, meals });
|
|
186
|
+
return data.getOrderDetail;
|
|
187
|
+
}
|
|
188
|
+
async searchMeals(keyword, date) {
|
|
189
|
+
const menu = await this.getMenu(date);
|
|
190
|
+
const term = keyword.toLowerCase();
|
|
191
|
+
return menu.meals.filter((meal) => {
|
|
192
|
+
if (meal.name.toLowerCase().includes(term))
|
|
193
|
+
return true;
|
|
194
|
+
if (meal.shortDescription.toLowerCase().includes(term))
|
|
195
|
+
return true;
|
|
196
|
+
const s = meal.searchBy;
|
|
197
|
+
if (s.cuisines.some((c) => c.toLowerCase().includes(term)))
|
|
198
|
+
return true;
|
|
199
|
+
if (s.dietTags.some((t) => t.toLowerCase().includes(term)))
|
|
200
|
+
return true;
|
|
201
|
+
if (s.ingredients.some((i) => i.toLowerCase().includes(term)))
|
|
202
|
+
return true;
|
|
203
|
+
if (s.proteinTags.some((p) => p.toLowerCase().includes(term)))
|
|
204
|
+
return true;
|
|
205
|
+
if (`${s.chefFirstName} ${s.chefLastName}`.toLowerCase().includes(term))
|
|
206
|
+
return true;
|
|
207
|
+
if (meal.category.title.toLowerCase().includes(term))
|
|
208
|
+
return true;
|
|
209
|
+
return false;
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
// --- private helpers ---
|
|
213
|
+
async queryMenu(query, variables = {}) {
|
|
214
|
+
return this.executeGraphQL(MENU_SERVICE_URL, query, variables);
|
|
215
|
+
}
|
|
216
|
+
async querySubscription(query, variables = {}) {
|
|
217
|
+
return this.executeGraphQL(SUBSCRIPTION_URL, query, variables);
|
|
218
|
+
}
|
|
219
|
+
async executeGraphQL(endpoint, query, variables = {}) {
|
|
220
|
+
const accessToken = await this.auth.getAccessToken();
|
|
221
|
+
try {
|
|
222
|
+
const response = await axios.post(endpoint, { query, variables }, {
|
|
223
|
+
headers: {
|
|
224
|
+
Authorization: `Bearer ${accessToken}`,
|
|
225
|
+
"Content-Type": "application/json",
|
|
226
|
+
"User-Agent": "CookUnity-MCP/1.0.0",
|
|
227
|
+
},
|
|
228
|
+
timeout: 30000,
|
|
229
|
+
});
|
|
230
|
+
const body = response.data;
|
|
231
|
+
if (body.errors) {
|
|
232
|
+
throw new Error(`GraphQL errors: ${body.errors.map((e) => e.message).join(", ")}`);
|
|
233
|
+
}
|
|
234
|
+
return body.data;
|
|
235
|
+
}
|
|
236
|
+
catch (error) {
|
|
237
|
+
if (error instanceof AxiosError) {
|
|
238
|
+
const status = error.response?.status;
|
|
239
|
+
if (status === 401)
|
|
240
|
+
throw new Error("Authentication expired. Please check your COOKUNITY_EMAIL and COOKUNITY_PASSWORD.");
|
|
241
|
+
if (status === 429)
|
|
242
|
+
throw new Error("Rate limited by CookUnity API. Please wait before retrying.");
|
|
243
|
+
throw new Error(`CookUnity API error (HTTP ${status ?? "unknown"}): ${error.message}`);
|
|
244
|
+
}
|
|
245
|
+
throw error;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
//# sourceMappingURL=api.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api.js","sourceRoot":"","sources":["../../src/services/api.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export declare class CookUnityAuth {
|
|
2
|
+
private email;
|
|
3
|
+
private password;
|
|
4
|
+
private tokens;
|
|
5
|
+
constructor(email: string, password: string);
|
|
6
|
+
getAccessToken(): Promise<string>;
|
|
7
|
+
private isTokenValid;
|
|
8
|
+
private authenticate;
|
|
9
|
+
private getLoginTicket;
|
|
10
|
+
private authorize;
|
|
11
|
+
private exchangeCodeForTokens;
|
|
12
|
+
private getErrorMessage;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=auth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/services/auth.ts"],"names":[],"mappings":"AAIA,qBAAa,aAAa;IACxB,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,MAAM,CAA2B;gBAE7B,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM;IAKrC,cAAc,IAAI,OAAO,CAAC,MAAM,CAAC;IAQvC,OAAO,CAAC,YAAY;YAIN,YAAY;YAeZ,cAAc;YAgBd,SAAS;YAuBT,qBAAqB;IAiBnC,OAAO,CAAC,eAAe;CASxB"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import axios, { AxiosError } from "axios";
|
|
2
|
+
import { AUTH_BASE_URL, AUTH_CLIENT_ID, AUTH_REALM } from "../constants.js";
|
|
3
|
+
export class CookUnityAuth {
|
|
4
|
+
email;
|
|
5
|
+
password;
|
|
6
|
+
tokens = null;
|
|
7
|
+
constructor(email, password) {
|
|
8
|
+
this.email = email;
|
|
9
|
+
this.password = password;
|
|
10
|
+
}
|
|
11
|
+
async getAccessToken() {
|
|
12
|
+
if (this.tokens && this.isTokenValid(this.tokens)) {
|
|
13
|
+
return this.tokens.access_token;
|
|
14
|
+
}
|
|
15
|
+
await this.authenticate();
|
|
16
|
+
return this.tokens.access_token;
|
|
17
|
+
}
|
|
18
|
+
isTokenValid(tokens) {
|
|
19
|
+
return Date.now() < tokens.expires_at - 60000;
|
|
20
|
+
}
|
|
21
|
+
async authenticate() {
|
|
22
|
+
try {
|
|
23
|
+
const loginTicket = await this.getLoginTicket();
|
|
24
|
+
const authCode = await this.authorize(loginTicket);
|
|
25
|
+
const tokenData = await this.exchangeCodeForTokens(authCode);
|
|
26
|
+
this.tokens = {
|
|
27
|
+
access_token: tokenData.access_token,
|
|
28
|
+
refresh_token: tokenData.refresh_token,
|
|
29
|
+
expires_at: Date.now() + tokenData.expires_in * 1000,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
catch (error) {
|
|
33
|
+
throw new Error(`Authentication failed: ${this.getErrorMessage(error)}`);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
async getLoginTicket() {
|
|
37
|
+
const response = await axios.post(`${AUTH_BASE_URL}/co/authenticate`, {
|
|
38
|
+
client_id: AUTH_CLIENT_ID,
|
|
39
|
+
credential_type: "password",
|
|
40
|
+
username: this.email,
|
|
41
|
+
password: this.password,
|
|
42
|
+
realm: AUTH_REALM,
|
|
43
|
+
}, { headers: { "Content-Type": "application/json", "User-Agent": "CookUnity-MCP/1.0.0" } });
|
|
44
|
+
if (!response.data.login_ticket)
|
|
45
|
+
throw new Error("Failed to get login ticket");
|
|
46
|
+
return response.data.login_ticket;
|
|
47
|
+
}
|
|
48
|
+
async authorize(loginTicket) {
|
|
49
|
+
const params = new URLSearchParams({
|
|
50
|
+
client_id: AUTH_CLIENT_ID,
|
|
51
|
+
response_type: "code",
|
|
52
|
+
redirect_uri: "https://app.cookunity.com/auth/callback",
|
|
53
|
+
scope: "openid profile email",
|
|
54
|
+
state: "cookunity_mcp",
|
|
55
|
+
realm: AUTH_REALM,
|
|
56
|
+
login_ticket: loginTicket,
|
|
57
|
+
});
|
|
58
|
+
const response = await axios.get(`${AUTH_BASE_URL}/authorize?${params}`, {
|
|
59
|
+
maxRedirects: 0,
|
|
60
|
+
validateStatus: (status) => status === 302,
|
|
61
|
+
headers: { "User-Agent": "CookUnity-MCP/1.0.0" },
|
|
62
|
+
});
|
|
63
|
+
const location = response.headers.location;
|
|
64
|
+
if (!location)
|
|
65
|
+
throw new Error("No redirect location in authorize response");
|
|
66
|
+
const url = new URL(location);
|
|
67
|
+
const code = url.searchParams.get("code");
|
|
68
|
+
if (!code)
|
|
69
|
+
throw new Error("No authorization code in callback URL");
|
|
70
|
+
return code;
|
|
71
|
+
}
|
|
72
|
+
async exchangeCodeForTokens(code) {
|
|
73
|
+
const response = await axios.post(`${AUTH_BASE_URL}/oauth/token`, {
|
|
74
|
+
grant_type: "authorization_code",
|
|
75
|
+
client_id: AUTH_CLIENT_ID,
|
|
76
|
+
code,
|
|
77
|
+
redirect_uri: "https://app.cookunity.com/auth/callback",
|
|
78
|
+
}, { headers: { "Content-Type": "application/json", "User-Agent": "CookUnity-MCP/1.0.0" } });
|
|
79
|
+
if (!response.data.access_token)
|
|
80
|
+
throw new Error("Failed to get access token");
|
|
81
|
+
return response.data;
|
|
82
|
+
}
|
|
83
|
+
getErrorMessage(error) {
|
|
84
|
+
if (error instanceof AxiosError) {
|
|
85
|
+
const data = error.response?.data;
|
|
86
|
+
if (data?.error_description)
|
|
87
|
+
return String(data.error_description);
|
|
88
|
+
if (data?.message)
|
|
89
|
+
return String(data.message);
|
|
90
|
+
if (error.response?.status)
|
|
91
|
+
return `HTTP ${error.response.status}: ${error.response.statusText}`;
|
|
92
|
+
}
|
|
93
|
+
return error instanceof Error ? error.message : "Unknown error";
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=auth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/services/auth.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AAE1C,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE5E,MAAM,OAAO,aAAa;IAChB,KAAK,CAAS;IACd,QAAQ,CAAS;IACjB,MAAM,GAAsB,IAAI,CAAC;IAEzC,YAAY,KAAa,EAAE,QAAgB;QACzC,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC3B,CAAC;IAED,KAAK,CAAC,cAAc;QAClB,IAAI,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;YAClD,OAAO,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC;QAClC,CAAC;QACD,MAAM,IAAI,CAAC,YAAY,EAAE,CAAC;QAC1B,OAAO,IAAI,CAAC,MAAO,CAAC,YAAY,CAAC;IACnC,CAAC;IAEO,YAAY,CAAC,MAAkB;QACrC,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,MAAM,CAAC,UAAU,GAAG,KAAK,CAAC;IAChD,CAAC;IAEO,KAAK,CAAC,YAAY;QACxB,IAAI,CAAC;YACH,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,cAAc,EAAE,CAAC;YAChD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;YACnD,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,qBAAqB,CAAC,QAAQ,CAAC,CAAC;YAC7D,IAAI,CAAC,MAAM,GAAG;gBACZ,YAAY,EAAE,SAAS,CAAC,YAAY;gBACpC,aAAa,EAAE,SAAS,CAAC,aAAa;gBACtC,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,GAAI,SAAS,CAAC,UAAqB,GAAG,IAAI;aACjE,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,IAAI,KAAK,CAAC,0BAA0B,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAC3E,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,cAAc;QAC1B,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,IAAI,CAC/B,GAAG,aAAa,kBAAkB,EAClC;YACE,SAAS,EAAE,cAAc;YACzB,eAAe,EAAE,UAAU;YAC3B,QAAQ,EAAE,IAAI,CAAC,KAAK;YACpB,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,KAAK,EAAE,UAAU;SAClB,EACD,EAAE,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,YAAY,EAAE,qBAAqB,EAAE,EAAE,CACzF,CAAC;QACF,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,YAAY;YAAE,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;QAC/E,OAAO,QAAQ,CAAC,IAAI,CAAC,YAAsB,CAAC;IAC9C,CAAC;IAEO,KAAK,CAAC,SAAS,CAAC,WAAmB;QACzC,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC;YACjC,SAAS,EAAE,cAAc;YACzB,aAAa,EAAE,MAAM;YACrB,YAAY,EAAE,yCAAyC;YACvD,KAAK,EAAE,sBAAsB;YAC7B,KAAK,EAAE,eAAe;YACtB,KAAK,EAAE,UAAU;YACjB,YAAY,EAAE,WAAW;SAC1B,CAAC,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,GAAG,aAAa,cAAc,MAAM,EAAE,EAAE;YACvE,YAAY,EAAE,CAAC;YACf,cAAc,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,KAAK,GAAG;YAC1C,OAAO,EAAE,EAAE,YAAY,EAAE,qBAAqB,EAAE;SACjD,CAAC,CAAC;QACH,MAAM,QAAQ,GAAG,QAAQ,CAAC,OAAO,CAAC,QAA8B,CAAC;QACjE,IAAI,CAAC,QAAQ;YAAE,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC;QAC7E,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC9B,MAAM,IAAI,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAC1C,IAAI,CAAC,IAAI;YAAE,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;QACpE,OAAO,IAAI,CAAC;IACd,CAAC;IAEO,KAAK,CAAC,qBAAqB,CACjC,IAAY;QAEZ,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,IAAI,CAC/B,GAAG,aAAa,cAAc,EAC9B;YACE,UAAU,EAAE,oBAAoB;YAChC,SAAS,EAAE,cAAc;YACzB,IAAI;YACJ,YAAY,EAAE,yCAAyC;SACxD,EACD,EAAE,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,YAAY,EAAE,qBAAqB,EAAE,EAAE,CACzF,CAAC;QACF,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,YAAY;YAAE,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;QAC/E,OAAO,QAAQ,CAAC,IAA4E,CAAC;IAC/F,CAAC;IAEO,eAAe,CAAC,KAAc;QACpC,IAAI,KAAK,YAAY,UAAU,EAAE,CAAC;YAChC,MAAM,IAAI,GAAG,KAAK,CAAC,QAAQ,EAAE,IAA2C,CAAC;YACzE,IAAI,IAAI,EAAE,iBAAiB;gBAAE,OAAO,MAAM,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;YACnE,IAAI,IAAI,EAAE,OAAO;gBAAE,OAAO,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAC/C,IAAI,KAAK,CAAC,QAAQ,EAAE,MAAM;gBAAE,OAAO,QAAQ,KAAK,CAAC,QAAQ,CAAC,MAAM,KAAK,KAAK,CAAC,QAAQ,CAAC,UAAU,EAAE,CAAC;QACnG,CAAC;QACD,OAAO,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC;IAClE,CAAC;CACF"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { Meal, FormattedMeal, UpcomingDay, DeliveryInfo } from "../types.js";
|
|
2
|
+
export declare function getNextMonday(): string;
|
|
3
|
+
export declare function formatMeal(meal: Meal): FormattedMeal;
|
|
4
|
+
export declare function formatDelivery(day: UpcomingDay): DeliveryInfo;
|
|
5
|
+
export declare function formatMealMarkdown(m: FormattedMeal): string;
|
|
6
|
+
export declare function truncateIfNeeded<T>(items: T[], textContent: string): {
|
|
7
|
+
items: T[];
|
|
8
|
+
truncated: boolean;
|
|
9
|
+
message?: string;
|
|
10
|
+
};
|
|
11
|
+
interface ToolResult {
|
|
12
|
+
[x: string]: unknown;
|
|
13
|
+
content: Array<{
|
|
14
|
+
type: "text";
|
|
15
|
+
text: string;
|
|
16
|
+
}>;
|
|
17
|
+
structuredContent?: Record<string, unknown>;
|
|
18
|
+
isError?: boolean;
|
|
19
|
+
}
|
|
20
|
+
export declare function handleError(error: unknown): ToolResult;
|
|
21
|
+
export declare function toStructured(obj: unknown): Record<string, unknown>;
|
|
22
|
+
export {};
|
|
23
|
+
//# sourceMappingURL=helpers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../src/services/helpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,aAAa,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAGlF,wBAAgB,aAAa,IAAI,MAAM,CAOtC;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,IAAI,GAAG,aAAa,CAyBpD;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,WAAW,GAAG,YAAY,CAwB7D;AAED,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,aAAa,GAAG,MAAM,CAW3D;AAED,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,WAAW,EAAE,MAAM,GAAG;IAAE,KAAK,EAAE,CAAC,EAAE,CAAC;IAAC,SAAS,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,CAQzH;AAGD,UAAU,UAAU;IAClB,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IACrB,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC/C,iBAAiB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC5C,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,UAAU,CAMtD;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAElE"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { CHARACTER_LIMIT } from "../constants.js";
|
|
2
|
+
export function getNextMonday() {
|
|
3
|
+
const today = new Date();
|
|
4
|
+
const dayOfWeek = today.getDay();
|
|
5
|
+
const daysUntilMonday = dayOfWeek === 0 ? 1 : 8 - dayOfWeek;
|
|
6
|
+
const nextMonday = new Date(today);
|
|
7
|
+
nextMonday.setDate(today.getDate() + daysUntilMonday);
|
|
8
|
+
return nextMonday.toISOString().split("T")[0];
|
|
9
|
+
}
|
|
10
|
+
export function formatMeal(meal) {
|
|
11
|
+
return {
|
|
12
|
+
id: meal.id,
|
|
13
|
+
name: meal.name,
|
|
14
|
+
description: meal.shortDescription,
|
|
15
|
+
chef: `${meal.chef.firstName} ${meal.chef.lastName}`,
|
|
16
|
+
category: meal.category.title,
|
|
17
|
+
price: meal.finalPrice,
|
|
18
|
+
original_price: meal.price,
|
|
19
|
+
rating: meal.userRating,
|
|
20
|
+
inventory_id: meal.inventoryId,
|
|
21
|
+
batch_id: meal.batchId,
|
|
22
|
+
in_stock: meal.stock > 0,
|
|
23
|
+
stock: meal.stock,
|
|
24
|
+
is_new: meal.isNewMeal,
|
|
25
|
+
image: meal.image,
|
|
26
|
+
nutrition: meal.nutritionalFacts,
|
|
27
|
+
tags: {
|
|
28
|
+
cuisines: meal.searchBy.cuisines,
|
|
29
|
+
diet_tags: meal.searchBy.dietTags,
|
|
30
|
+
protein_tags: meal.searchBy.proteinTags,
|
|
31
|
+
ingredients: meal.searchBy.ingredients,
|
|
32
|
+
},
|
|
33
|
+
meat_type: meal.meatType,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
export function formatDelivery(day) {
|
|
37
|
+
const status = !day.canEdit
|
|
38
|
+
? "locked"
|
|
39
|
+
: day.skip
|
|
40
|
+
? "skipped"
|
|
41
|
+
: day.isPaused
|
|
42
|
+
? "paused"
|
|
43
|
+
: "active";
|
|
44
|
+
return {
|
|
45
|
+
date: day.displayDate,
|
|
46
|
+
status,
|
|
47
|
+
can_edit: day.canEdit,
|
|
48
|
+
menu_available: day.menuAvailable,
|
|
49
|
+
cutoff: day.cutoff?.time ?? null,
|
|
50
|
+
cutoff_timezone: day.cutoff?.userTimeZone ?? null,
|
|
51
|
+
cart_items: (day.cart || []).map((c) => ({
|
|
52
|
+
name: c.product?.name ?? "Unknown",
|
|
53
|
+
inventory_id: c.product?.inventoryId ?? "",
|
|
54
|
+
quantity: c.qty,
|
|
55
|
+
price: c.product?.price_incl_tax ?? 0,
|
|
56
|
+
chef: `${c.product?.chef_firstname ?? ""} ${c.product?.chef_lastname ?? ""}`.trim(),
|
|
57
|
+
})),
|
|
58
|
+
cart_count: (day.cart || []).reduce((sum, c) => sum + (c.qty || 0), 0),
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
export function formatMealMarkdown(m) {
|
|
62
|
+
const lines = [
|
|
63
|
+
`### ${m.name}${m.is_new ? " 🆕" : ""}`,
|
|
64
|
+
`**Chef**: ${m.chef} | **Category**: ${m.category}`,
|
|
65
|
+
`**Price**: $${m.price.toFixed(2)}${m.price !== m.original_price ? ` (was $${m.original_price.toFixed(2)})` : ""} | **Rating**: ${m.rating}/5`,
|
|
66
|
+
`**Stock**: ${m.in_stock ? m.stock : "Out of stock"} | **Inventory ID**: \`${m.inventory_id}\``,
|
|
67
|
+
m.description,
|
|
68
|
+
`🥩 ${m.meat_type} | ${m.nutrition.calories} cal`,
|
|
69
|
+
];
|
|
70
|
+
if (m.tags.diet_tags.length > 0)
|
|
71
|
+
lines.push(`🏷️ ${m.tags.diet_tags.join(", ")}`);
|
|
72
|
+
return lines.join("\n");
|
|
73
|
+
}
|
|
74
|
+
export function truncateIfNeeded(items, textContent) {
|
|
75
|
+
if (textContent.length <= CHARACTER_LIMIT)
|
|
76
|
+
return { items, truncated: false };
|
|
77
|
+
const reduced = items.slice(0, Math.max(1, Math.floor(items.length / 2)));
|
|
78
|
+
return {
|
|
79
|
+
items: reduced,
|
|
80
|
+
truncated: true,
|
|
81
|
+
message: `Response truncated from ${items.length} to ${reduced.length} items. Use offset/limit or filters to see more.`,
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
export function handleError(error) {
|
|
85
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
86
|
+
return {
|
|
87
|
+
content: [{ type: "text", text: `Error: ${message}` }],
|
|
88
|
+
isError: true,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
export function toStructured(obj) {
|
|
92
|
+
return JSON.parse(JSON.stringify(obj));
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=helpers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../src/services/helpers.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cart.d.ts","sourceRoot":"","sources":["../../src/tools/cart.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAKvD,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,EAAE,YAAY,GAAG,IAAI,CAyM5E"}
|