mcp-recipes 1.3.0 → 2.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/CHANGELOG.md +21 -0
- package/README.md +41 -3
- package/dist/index.js +1298 -552
- package/dist/index.js.map +1 -1
- package/dist/recipe/scale.js +861 -326
- package/dist/recipe/scale.js.map +1 -1
- package/dist/sources/client.d.ts +13 -133
- package/dist/sources/client.js +217 -153
- package/dist/sources/client.js.map +1 -1
- package/package.json +18 -9
- package/server.json +78 -0
package/dist/sources/client.d.ts
CHANGED
|
@@ -24,10 +24,10 @@ interface Config {
|
|
|
24
24
|
logLevel: LogLevel;
|
|
25
25
|
}
|
|
26
26
|
interface Logger {
|
|
27
|
-
debug(message: string)
|
|
28
|
-
info(message: string)
|
|
29
|
-
warn(message: string)
|
|
30
|
-
error(message: string)
|
|
27
|
+
debug: (message: string) => void;
|
|
28
|
+
info: (message: string) => void;
|
|
29
|
+
warn: (message: string) => void;
|
|
30
|
+
error: (message: string) => void;
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
/** The shapes the source layer produces. Nothing here knows about MCP. */
|
|
@@ -249,12 +249,10 @@ interface SourceAdapter extends SourceProfile {
|
|
|
249
249
|
* no source claims is refused, instead of being sent somewhere that would
|
|
250
250
|
* answer it with a confident absence.
|
|
251
251
|
*/
|
|
252
|
-
claims(raw: string)
|
|
253
|
-
search(query: string, limit: number)
|
|
254
|
-
getRecipe(reference: string)
|
|
252
|
+
claims: (raw: string) => Claim | null;
|
|
253
|
+
search: (query: string, limit: number) => Promise<ReadRows>;
|
|
254
|
+
getRecipe: (reference: string) => Promise<ReadRecipe>;
|
|
255
255
|
}
|
|
256
|
-
/** Build the identifier this server hands out for a row from a source. */
|
|
257
|
-
declare function namespacedId(source: SourceId, reference: string): string;
|
|
258
256
|
|
|
259
257
|
/**
|
|
260
258
|
* Identifiers that name the source they came from.
|
|
@@ -272,21 +270,6 @@ interface ResolvedId {
|
|
|
272
270
|
/** Set when the shape was read rather than stated, so the answer can say so. */
|
|
273
271
|
inferred: string | null;
|
|
274
272
|
}
|
|
275
|
-
/**
|
|
276
|
-
* Work out which source an identifier belongs to.
|
|
277
|
-
*
|
|
278
|
-
* A prefixed identifier is routed on what it says. A raw one is offered to each
|
|
279
|
-
* source in turn, and a source claims only the shapes it mints: digits for one,
|
|
280
|
-
* a namespaced page key for another. Exactly one claim routes the read and the
|
|
281
|
-
* answer says which reading it used.
|
|
282
|
-
*
|
|
283
|
-
* More than one claim is refused rather than resolved, because picking a winner
|
|
284
|
-
* would send the read somewhere a caller did not intend and answer with a
|
|
285
|
-
* confident recipe for the wrong dish. No claim at all is refused too: a bare
|
|
286
|
-
* dish name is a search, not an identifier, and guessing a page name from it
|
|
287
|
-
* returns whatever that guess happens to hit.
|
|
288
|
-
*/
|
|
289
|
-
declare function resolveId(rawId: string, sources: readonly SourceAdapter[]): ResolvedId;
|
|
290
273
|
|
|
291
274
|
/**
|
|
292
275
|
* The Cookbook on the English Wikibooks, as a source.
|
|
@@ -329,13 +312,13 @@ interface CookbookRecipe {
|
|
|
329
312
|
}
|
|
330
313
|
/** The part of the Cookbook's client this server uses. */
|
|
331
314
|
interface CookbookReader {
|
|
332
|
-
search(query: string, limit: number)
|
|
315
|
+
search: (query: string, limit: number) => Promise<{
|
|
333
316
|
data: {
|
|
334
317
|
results: CookbookSummary[];
|
|
335
318
|
};
|
|
336
319
|
cached: boolean;
|
|
337
320
|
}>;
|
|
338
|
-
getRecipe(reference: string)
|
|
321
|
+
getRecipe: (reference: string) => Promise<{
|
|
339
322
|
data: CookbookRecipe;
|
|
340
323
|
cached: boolean;
|
|
341
324
|
}>;
|
|
@@ -382,14 +365,14 @@ interface MarmitonRecipe {
|
|
|
382
365
|
}
|
|
383
366
|
/** The part of Marmiton's client this server uses. */
|
|
384
367
|
interface MarmitonReader {
|
|
385
|
-
search(query: string)
|
|
368
|
+
search: (query: string) => Promise<{
|
|
386
369
|
data: MarmitonSummary[];
|
|
387
370
|
cached: boolean;
|
|
388
371
|
}>;
|
|
389
|
-
getRecipe(ref: {
|
|
372
|
+
getRecipe: (ref: {
|
|
390
373
|
id?: string;
|
|
391
374
|
url?: string;
|
|
392
|
-
})
|
|
375
|
+
}) => Promise<{
|
|
393
376
|
data: MarmitonRecipe;
|
|
394
377
|
cached: boolean;
|
|
395
378
|
}>;
|
|
@@ -412,109 +395,6 @@ interface Readers {
|
|
|
412
395
|
marmiton?: MarmitonReader;
|
|
413
396
|
cookbook?: CookbookReader;
|
|
414
397
|
}
|
|
415
|
-
/** The sources a caller can name, in the order an answer takes them. */
|
|
416
|
-
declare const SOURCE_IDS: readonly SourceId[];
|
|
417
|
-
|
|
418
|
-
/**
|
|
419
|
-
* Several wordings from one question.
|
|
420
|
-
*
|
|
421
|
-
* A person asks for a recipe in a sentence, and a recipe index reads none of
|
|
422
|
-
* it. One of the indexes behind this server requires every word given to appear
|
|
423
|
-
* on the same page, so a sentence returns nothing where the corpus holds several
|
|
424
|
-
* of the dish. The other ranks pages on the words it was handed, so the words
|
|
425
|
-
* framing the question pull up whatever happens to share them and push the dish
|
|
426
|
-
* down the list or out of it. Both come back to a reader looking like a
|
|
427
|
-
* statement about a corpus when they are statements about a wording. Deriving
|
|
428
|
-
* the shorter wordings and asking for the union is what keeps the two apart.
|
|
429
|
-
*
|
|
430
|
-
* Every wording is built from the words the question carried, with no
|
|
431
|
-
* dictionary, no corpus statistics and no translation. That has two
|
|
432
|
-
* consequences worth stating. A derived wording is one a reader can retype by
|
|
433
|
-
* hand, so an answer built from several of them stays checkable. And the
|
|
434
|
-
* derivations that would need a lexicon are not made: a question asked in one
|
|
435
|
-
* language is never turned into the other, because a source that publishes in
|
|
436
|
-
* the other language and holds nothing under the words written is an honest
|
|
437
|
-
* absence, while a guessed translation is a word nobody wrote.
|
|
438
|
-
*
|
|
439
|
-
* The order runs from the wording closest to what was asked to the widest.
|
|
440
|
-
*
|
|
441
|
-
* A question also states what the recipe must not hold, and that part is read
|
|
442
|
-
* by the role its words play rather than by the turn of phrase they are written
|
|
443
|
-
* in: a negation, a sentence about how a food affects the person, or the name
|
|
444
|
-
* of a diet. All three put a food out of the dish, so all three are set aside
|
|
445
|
-
* from the derived wordings and named back to the caller. Reading them off a
|
|
446
|
-
* list of phrasings is what lets a declared allergen become a word to search
|
|
447
|
-
* for, and there is no phrasing whose absence from such a list is safe.
|
|
448
|
-
*/
|
|
449
|
-
/** One wording, and how it was arrived at. */
|
|
450
|
-
interface Wording {
|
|
451
|
-
query: string;
|
|
452
|
-
/** How this wording was derived from the question, in words. */
|
|
453
|
-
derivation: string;
|
|
454
|
-
}
|
|
455
|
-
/**
|
|
456
|
-
* The most searches one source receives for one question.
|
|
457
|
-
*
|
|
458
|
-
* A ceiling per source rather than a budget shared between them, because the
|
|
459
|
-
* sources are asked in parallel and each is paced on its own, so the worst case
|
|
460
|
-
* is three of one source's intervals rather than six. Three is also the whole
|
|
461
|
-
* ladder: the question as asked, the dish words, and the word naming the dish.
|
|
462
|
-
*/
|
|
463
|
-
declare const MAX_WORDINGS_PER_SOURCE = 3;
|
|
464
|
-
/** How a question put a condition, which decides how it is reported back. */
|
|
465
|
-
type ConditionKind =
|
|
466
|
-
/** The question wrote the recipe must not hold this. */
|
|
467
|
-
"excluded"
|
|
468
|
-
/** The question said the person reacts to this food. */
|
|
469
|
-
| "allergy"
|
|
470
|
-
/** The question named a diet, which is a class defined by what it leaves out. */
|
|
471
|
-
| "diet";
|
|
472
|
-
/** One thing a question asks the recipe not to hold. */
|
|
473
|
-
interface Condition {
|
|
474
|
-
/**
|
|
475
|
-
* The words the question used for the food, or null where the question states
|
|
476
|
-
* a condition and the sentence does not say plainly which food it covers.
|
|
477
|
-
*
|
|
478
|
-
* A word named here is a word the recipe must not hold and a word no wording
|
|
479
|
-
* looks for, so naming the wrong one both hides a dish and leaves the food
|
|
480
|
-
* being avoided in the search. Where the reading is not certain, the caller is
|
|
481
|
-
* told a condition was stated and that its food was not read, which is a
|
|
482
|
-
* smaller claim than either.
|
|
483
|
-
*/
|
|
484
|
-
named: string | null;
|
|
485
|
-
kind: ConditionKind;
|
|
486
|
-
}
|
|
487
|
-
/** What a question asks the dish to avoid, and how many it has to serve. */
|
|
488
|
-
interface Conditions {
|
|
489
|
-
/** What the dish must not hold, in the words the question used. */
|
|
490
|
-
conditions: Condition[];
|
|
491
|
-
/** How many the dish has to serve, when the question said. */
|
|
492
|
-
servings: number | null;
|
|
493
|
-
}
|
|
494
|
-
/**
|
|
495
|
-
* Read what the question asks the recipe to avoid or to serve.
|
|
496
|
-
*
|
|
497
|
-
* These are the parts of a question no recipe index answers. A page is not
|
|
498
|
-
* named for what it leaves out, and the number of people at a table is not
|
|
499
|
-
* printed in a title at all, so both are read here and handled as what they
|
|
500
|
-
* are rather than as words to look for.
|
|
501
|
-
*/
|
|
502
|
-
declare function readConditions(question: string): Conditions;
|
|
503
|
-
declare function deriveWordings(question: string): Wording[];
|
|
504
|
-
/**
|
|
505
|
-
* Whether a row's title carries a word naming the dish that was asked for.
|
|
506
|
-
*
|
|
507
|
-
* This decides whether a wording answered, and nothing else: no row is dropped
|
|
508
|
-
* and no row is moved for failing it. A source that ranks on the words it was
|
|
509
|
-
* handed answers a sentence with a page of recipes that share its framing
|
|
510
|
-
* words, and counting those as an answer would stop the search on the page that
|
|
511
|
-
* proves it has not found the dish.
|
|
512
|
-
*
|
|
513
|
-
* Diacritics and punctuation fold away, so "crêpes" reads the same as "crepes"
|
|
514
|
-
* and a namespace in front of a page name settles nothing. A question that
|
|
515
|
-
* names no dish has nothing to check against, and every row passes.
|
|
516
|
-
*/
|
|
517
|
-
declare function namesDish(title: string, question: string): boolean;
|
|
518
398
|
|
|
519
399
|
/**
|
|
520
400
|
* The one place that talks to the sources.
|
|
@@ -622,4 +502,4 @@ declare class RecipesClient {
|
|
|
622
502
|
}>;
|
|
623
503
|
}
|
|
624
504
|
|
|
625
|
-
export { type
|
|
505
|
+
export { type CookbookReader, MAX_LIMIT_PER_SOURCE, type MarmitonReader, type MergedSearch, type ReadRecipe, type ReadRows, type Readers, type RecipeDetail, type RecipeRow, RecipesClient, type RecipesClientOptions, type SearchOptions, type SourceAdapter, type SourceId, type SourceProfile, type SourceReport, type WordingAttempt, interleave };
|