@cyanheads/interpro-mcp-server 0.0.0-stage → 0.1.2
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/AGENTS.md +376 -0
- package/CLAUDE.md +376 -0
- package/Dockerfile +186 -0
- package/LICENSE +201 -0
- package/README.md +289 -2
- package/changelog/0.1.x/0.1.1.md +20 -0
- package/changelog/0.1.x/0.1.2.md +27 -0
- package/changelog/template.md +151 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +34 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp-server/tools/definitions/interpro-find-proteins-by-domain.tool.d.ts +180 -0
- package/dist/mcp-server/tools/definitions/interpro-find-proteins-by-domain.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/interpro-find-proteins-by-domain.tool.js +212 -0
- package/dist/mcp-server/tools/definitions/interpro-find-proteins-by-domain.tool.js.map +1 -0
- package/dist/mcp-server/tools/definitions/interpro-get-clan.tool.d.ts +160 -0
- package/dist/mcp-server/tools/definitions/interpro-get-clan.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/interpro-get-clan.tool.js +259 -0
- package/dist/mcp-server/tools/definitions/interpro-get-clan.tool.js.map +1 -0
- package/dist/mcp-server/tools/definitions/interpro-get-entry.tool.d.ts +131 -0
- package/dist/mcp-server/tools/definitions/interpro-get-entry.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/interpro-get-entry.tool.js +105 -0
- package/dist/mcp-server/tools/definitions/interpro-get-entry.tool.js.map +1 -0
- package/dist/mcp-server/tools/definitions/interpro-get-protein-domains.tool.d.ts +172 -0
- package/dist/mcp-server/tools/definitions/interpro-get-protein-domains.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/interpro-get-protein-domains.tool.js +374 -0
- package/dist/mcp-server/tools/definitions/interpro-get-protein-domains.tool.js.map +1 -0
- package/dist/mcp-server/tools/definitions/interpro-list-reference.tool.d.ts +89 -0
- package/dist/mcp-server/tools/definitions/interpro-list-reference.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/interpro-list-reference.tool.js +99 -0
- package/dist/mcp-server/tools/definitions/interpro-list-reference.tool.js.map +1 -0
- package/dist/mcp-server/tools/definitions/interpro-search-entries.tool.d.ts +190 -0
- package/dist/mcp-server/tools/definitions/interpro-search-entries.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/interpro-search-entries.tool.js +165 -0
- package/dist/mcp-server/tools/definitions/interpro-search-entries.tool.js.map +1 -0
- package/dist/services/interpro/budget.d.ts +26 -0
- package/dist/services/interpro/budget.d.ts.map +1 -0
- package/dist/services/interpro/budget.js +41 -0
- package/dist/services/interpro/budget.js.map +1 -0
- package/dist/services/interpro/cursors.d.ts +25 -0
- package/dist/services/interpro/cursors.d.ts.map +1 -0
- package/dist/services/interpro/cursors.js +99 -0
- package/dist/services/interpro/cursors.js.map +1 -0
- package/dist/services/interpro/description-text.d.ts +3 -0
- package/dist/services/interpro/description-text.d.ts.map +1 -0
- package/dist/services/interpro/description-text.js +179 -0
- package/dist/services/interpro/description-text.js.map +1 -0
- package/dist/services/interpro/format.d.ts +17 -0
- package/dist/services/interpro/format.d.ts.map +1 -0
- package/dist/services/interpro/format.js +130 -0
- package/dist/services/interpro/format.js.map +1 -0
- package/dist/services/interpro/http-adapter.d.ts +11 -0
- package/dist/services/interpro/http-adapter.d.ts.map +1 -0
- package/dist/services/interpro/http-adapter.js +134 -0
- package/dist/services/interpro/http-adapter.js.map +1 -0
- package/dist/services/interpro/interpro-service.d.ts +57 -0
- package/dist/services/interpro/interpro-service.d.ts.map +1 -0
- package/dist/services/interpro/interpro-service.js +284 -0
- package/dist/services/interpro/interpro-service.js.map +1 -0
- package/dist/services/interpro/reference.d.ts +31 -0
- package/dist/services/interpro/reference.d.ts.map +1 -0
- package/dist/services/interpro/reference.js +122 -0
- package/dist/services/interpro/reference.js.map +1 -0
- package/dist/services/interpro/relationships.d.ts +38 -0
- package/dist/services/interpro/relationships.d.ts.map +1 -0
- package/dist/services/interpro/relationships.js +70 -0
- package/dist/services/interpro/relationships.js.map +1 -0
- package/dist/services/interpro/routing.d.ts +24 -0
- package/dist/services/interpro/routing.d.ts.map +1 -0
- package/dist/services/interpro/routing.js +106 -0
- package/dist/services/interpro/routing.js.map +1 -0
- package/dist/services/interpro/schemas.d.ts +192 -0
- package/dist/services/interpro/schemas.d.ts.map +1 -0
- package/dist/services/interpro/schemas.js +226 -0
- package/dist/services/interpro/schemas.js.map +1 -0
- package/dist/services/interpro/upstream-errors.d.ts +43 -0
- package/dist/services/interpro/upstream-errors.d.ts.map +1 -0
- package/dist/services/interpro/upstream-errors.js +49 -0
- package/dist/services/interpro/upstream-errors.js.map +1 -0
- package/package.json +104 -4
- package/server.json +91 -0
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Shared byte budget for one tool result's domain output, and whole-item fitting.
|
|
3
|
+
* @module services/interpro/budget
|
|
4
|
+
*/
|
|
5
|
+
/** Most UTF-8 bytes one result's domain output may occupy when serialized as compact JSON. */
|
|
6
|
+
export const RESPONSE_BYTE_BUDGET = 100_000;
|
|
7
|
+
/** UTF-8 bytes of a value serialized as compact JSON, the form both result surfaces carry. */
|
|
8
|
+
export function jsonByteLength(value) {
|
|
9
|
+
return Buffer.byteLength(JSON.stringify(value), 'utf8');
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* The largest count from 1 to `max` whose `build(count)` fits {@link RESPONSE_BYTE_BUDGET},
|
|
13
|
+
* found by binary search on the assumption that the built size grows with the count. Returns 1
|
|
14
|
+
* when even one item overflows, so a continuation always advances, and 0 when none remain.
|
|
15
|
+
*/
|
|
16
|
+
export function largestFittingCount(max, build) {
|
|
17
|
+
if (max <= 0)
|
|
18
|
+
return 0;
|
|
19
|
+
let fits = 1;
|
|
20
|
+
let overflows = max + 1;
|
|
21
|
+
while (overflows - fits > 1) {
|
|
22
|
+
const middle = Math.floor((fits + overflows) / 2);
|
|
23
|
+
if (jsonByteLength(build(middle)) <= RESPONSE_BYTE_BUDGET)
|
|
24
|
+
fits = middle;
|
|
25
|
+
else
|
|
26
|
+
overflows = middle;
|
|
27
|
+
}
|
|
28
|
+
return fits;
|
|
29
|
+
}
|
|
30
|
+
/** The budget as it reads in notices. */
|
|
31
|
+
export const BUDGET_LABEL = `${RESPONSE_BYTE_BUDGET.toLocaleString('en-US')}-byte response budget`;
|
|
32
|
+
/**
|
|
33
|
+
* Builds the largest whole-item output that fits the budget. `oversized` is set when even the
|
|
34
|
+
* smallest non-empty output exceeds it, so the output carries one indivisible item alone.
|
|
35
|
+
*/
|
|
36
|
+
export function fitWithinBudget(max, build) {
|
|
37
|
+
const count = largestFittingCount(max, build);
|
|
38
|
+
const output = build(count);
|
|
39
|
+
return { count, output, oversized: count > 0 && jsonByteLength(output) > RESPONSE_BYTE_BUDGET };
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=budget.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"budget.js","sourceRoot":"","sources":["../../../src/services/interpro/budget.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,8FAA8F;AAC9F,MAAM,CAAC,MAAM,oBAAoB,GAAG,OAAO,CAAC;AAE5C,8FAA8F;AAC9F,MAAM,UAAU,cAAc,CAAC,KAAc;IAC3C,OAAO,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC,CAAC;AAC1D,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CAAC,GAAW,EAAE,KAAiC;IAChF,IAAI,GAAG,IAAI,CAAC;QAAE,OAAO,CAAC,CAAC;IACvB,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,IAAI,SAAS,GAAG,GAAG,GAAG,CAAC,CAAC;IACxB,OAAO,SAAS,GAAG,IAAI,GAAG,CAAC,EAAE,CAAC;QAC5B,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC;QAClD,IAAI,cAAc,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,oBAAoB;YAAE,IAAI,GAAG,MAAM,CAAC;;YACpE,SAAS,GAAG,MAAM,CAAC;IAC1B,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,yCAAyC;AACzC,MAAM,CAAC,MAAM,YAAY,GAAG,GAAG,oBAAoB,CAAC,cAAc,CAAC,OAAO,CAAC,uBAAuB,CAAC;AAEnG;;;GAGG;AACH,MAAM,UAAU,eAAe,CAC7B,GAAW,EACX,KAA2B;IAE3B,MAAM,KAAK,GAAG,mBAAmB,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IAC9C,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC;IAC5B,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,KAAK,GAAG,CAAC,IAAI,cAAc,CAAC,MAAM,CAAC,GAAG,oBAAoB,EAAE,CAAC;AAClG,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Query-bound, versioned pagination tokens.
|
|
3
|
+
* @module services/interpro/cursors
|
|
4
|
+
*/
|
|
5
|
+
import { z } from '@cyanheads/mcp-ts-core';
|
|
6
|
+
/** Deterministic canonical scope, independent of object key insertion order. */
|
|
7
|
+
export declare function cursorScope(value: unknown): string;
|
|
8
|
+
/** Code-unit string order, the tiebreak used wherever a page boundary must be deterministic. */
|
|
9
|
+
export declare const compareText: (a: string, b: string) => -1 | 0 | 1;
|
|
10
|
+
/** Encode only the continuation value, never an upstream request URL. */
|
|
11
|
+
export declare function encodeCursor(operation: string, scope: unknown, upstreamCursor: string): string;
|
|
12
|
+
/** Reject malformed tokens and tokens reused with a changed target or filter. */
|
|
13
|
+
export declare function decodeCursor(token: string | undefined, operation: string, scope: unknown): string | undefined;
|
|
14
|
+
/** Encode a tool-defined resumption point, for walks that can stop inside an upstream page. */
|
|
15
|
+
export declare function encodePositionCursor(operation: string, scope: unknown, position: unknown): string;
|
|
16
|
+
/** Decode a resumption point and validate it against the tool's own position schema. */
|
|
17
|
+
export declare function decodePositionCursor<T extends z.ZodType>(token: string | undefined, operation: string, scope: unknown, schema: T): z.output<T> | undefined;
|
|
18
|
+
/**
|
|
19
|
+
* Truncation guidance for a capped cursor page: the call that continues it, plus a larger
|
|
20
|
+
* `limit` only while the current one is below the tool's maximum.
|
|
21
|
+
*/
|
|
22
|
+
export declare function pageGuidance(toolName: string, noun: string, limit: number, maxLimit: number): string;
|
|
23
|
+
/** Extract the sole usable continuation field without trusting URL origin/path. */
|
|
24
|
+
export declare function continuation(next: string | null, seen?: ReadonlySet<string>): string | undefined;
|
|
25
|
+
//# sourceMappingURL=cursors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cursors.d.ts","sourceRoot":"","sources":["../../../src/services/interpro/cursors.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,wBAAwB,CAAC;AAsB3C,gFAAgF;AAChF,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAMlD;AACD,gGAAgG;AAChG,eAAO,MAAM,WAAW,MAAO,MAAM,KAAK,MAAM,eAAiC,CAAC;AAkClF,yEAAyE;AACzE,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,GAAG,MAAM,CAE9F;AACD,iFAAiF;AACjF,wBAAgB,YAAY,CAC1B,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,OAAO,GACb,MAAM,GAAG,SAAS,CAKpB;AACD,+FAA+F;AAC/F,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,GAAG,MAAM,CAEjG;AACD,wFAAwF;AACxF,wBAAgB,oBAAoB,CAAC,CAAC,SAAS,CAAC,CAAC,OAAO,EACtD,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,OAAO,EACd,MAAM,EAAE,CAAC,GACR,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,SAAS,CAEzB;AACD;;;GAGG;AACH,wBAAgB,YAAY,CAC1B,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,GACf,MAAM,CAER;AACD,mFAAmF;AACnF,wBAAgB,YAAY,CAC1B,IAAI,EAAE,MAAM,GAAG,IAAI,EACnB,IAAI,GAAE,WAAW,CAAC,MAAM,CAAa,GACpC,MAAM,GAAG,SAAS,CAkBpB"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Query-bound, versioned pagination tokens.
|
|
3
|
+
* @module services/interpro/cursors
|
|
4
|
+
*/
|
|
5
|
+
import { z } from '@cyanheads/mcp-ts-core';
|
|
6
|
+
import { serviceUnavailable, validationError } from '@cyanheads/mcp-ts-core/errors';
|
|
7
|
+
import { API_BASE } from './routing.js';
|
|
8
|
+
/**
|
|
9
|
+
* Every token carries exactly one continuation: the upstream cursor of the next page, or a
|
|
10
|
+
* tool-defined position for a walk that resumes inside a page.
|
|
11
|
+
*/
|
|
12
|
+
const CursorSchema = z
|
|
13
|
+
.object({
|
|
14
|
+
v: z.literal(1),
|
|
15
|
+
operation: z.string().min(1),
|
|
16
|
+
scope: z.string(),
|
|
17
|
+
upstreamCursor: z.string().min(1).optional(),
|
|
18
|
+
position: z.json().optional(),
|
|
19
|
+
})
|
|
20
|
+
.strict()
|
|
21
|
+
.refine((cursor) => (cursor.upstreamCursor === undefined) !== (cursor.position === undefined), 'A cursor carries exactly one continuation.');
|
|
22
|
+
/** Deterministic canonical scope, independent of object key insertion order. */
|
|
23
|
+
export function cursorScope(value) {
|
|
24
|
+
return JSON.stringify(value, (_key, item) => item && typeof item === 'object' && !Array.isArray(item)
|
|
25
|
+
? Object.fromEntries(Object.entries(item).sort(([a], [b]) => a.localeCompare(b)))
|
|
26
|
+
: item);
|
|
27
|
+
}
|
|
28
|
+
/** Code-unit string order, the tiebreak used wherever a page boundary must be deterministic. */
|
|
29
|
+
export const compareText = (a, b) => (a < b ? -1 : a > b ? 1 : 0);
|
|
30
|
+
function seal(operation, scope, resumption) {
|
|
31
|
+
const token = Buffer.from(JSON.stringify({ v: 1, operation, scope: cursorScope(scope), ...resumption })).toString('base64url');
|
|
32
|
+
if (token.length > 4096)
|
|
33
|
+
throw serviceUnavailable('InterPro continuation exceeds the supported token size.', {
|
|
34
|
+
reason: 'upstream_shape_invalid',
|
|
35
|
+
retryable: false,
|
|
36
|
+
});
|
|
37
|
+
return token;
|
|
38
|
+
}
|
|
39
|
+
function open(token, operation, scope, read) {
|
|
40
|
+
if (token === undefined)
|
|
41
|
+
return undefined;
|
|
42
|
+
try {
|
|
43
|
+
if (token.length > 4096 || !/^[A-Za-z0-9_-]+$/.test(token))
|
|
44
|
+
throw new Error('Invalid cursor encoding.');
|
|
45
|
+
const parsed = CursorSchema.parse(JSON.parse(Buffer.from(token, 'base64url').toString('utf8')));
|
|
46
|
+
if (parsed.operation !== operation || parsed.scope !== cursorScope(scope))
|
|
47
|
+
throw new Error('Cursor scope differs.');
|
|
48
|
+
return read(parsed);
|
|
49
|
+
}
|
|
50
|
+
catch (cause) {
|
|
51
|
+
throw validationError('Cursor is invalid or belongs to a different query.', { reason: 'invalid_cursor', retryable: false }, { cause });
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
/** Encode only the continuation value, never an upstream request URL. */
|
|
55
|
+
export function encodeCursor(operation, scope, upstreamCursor) {
|
|
56
|
+
return seal(operation, scope, { upstreamCursor });
|
|
57
|
+
}
|
|
58
|
+
/** Reject malformed tokens and tokens reused with a changed target or filter. */
|
|
59
|
+
export function decodeCursor(token, operation, scope) {
|
|
60
|
+
return open(token, operation, scope, ({ upstreamCursor }) => {
|
|
61
|
+
if (upstreamCursor === undefined)
|
|
62
|
+
throw new Error('Cursor carries no upstream continuation.');
|
|
63
|
+
return upstreamCursor;
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
/** Encode a tool-defined resumption point, for walks that can stop inside an upstream page. */
|
|
67
|
+
export function encodePositionCursor(operation, scope, position) {
|
|
68
|
+
return seal(operation, scope, { position });
|
|
69
|
+
}
|
|
70
|
+
/** Decode a resumption point and validate it against the tool's own position schema. */
|
|
71
|
+
export function decodePositionCursor(token, operation, scope, schema) {
|
|
72
|
+
return open(token, operation, scope, ({ position }) => schema.parse(position));
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Truncation guidance for a capped cursor page: the call that continues it, plus a larger
|
|
76
|
+
* `limit` only while the current one is below the tool's maximum.
|
|
77
|
+
*/
|
|
78
|
+
export function pageGuidance(toolName, noun, limit, maxLimit) {
|
|
79
|
+
return `More ${noun} remain: repeat ${toolName} with the same arguments and cursor set to page.nextCursor${limit < maxLimit ? `; limit may rise to ${maxLimit} for larger pages` : ''}.`;
|
|
80
|
+
}
|
|
81
|
+
/** Extract the sole usable continuation field without trusting URL origin/path. */
|
|
82
|
+
export function continuation(next, seen = new Set()) {
|
|
83
|
+
if (next === null)
|
|
84
|
+
return undefined;
|
|
85
|
+
let cursor;
|
|
86
|
+
try {
|
|
87
|
+
cursor = new URL(next, API_BASE).searchParams.get('cursor');
|
|
88
|
+
}
|
|
89
|
+
catch (cause) {
|
|
90
|
+
throw serviceUnavailable('InterPro returned an invalid continuation URL.', { reason: 'upstream_shape_invalid', retryable: false }, { cause });
|
|
91
|
+
}
|
|
92
|
+
if (!cursor?.trim() || seen.has(cursor))
|
|
93
|
+
throw serviceUnavailable('InterPro returned a missing or repeated continuation cursor.', {
|
|
94
|
+
reason: 'upstream_shape_invalid',
|
|
95
|
+
retryable: false,
|
|
96
|
+
});
|
|
97
|
+
return cursor;
|
|
98
|
+
}
|
|
99
|
+
//# sourceMappingURL=cursors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cursors.js","sourceRoot":"","sources":["../../../src/services/interpro/cursors.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,wBAAwB,CAAC;AAC3C,OAAO,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AACpF,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAExC;;;GAGG;AACH,MAAM,YAAY,GAAG,CAAC;KACnB,MAAM,CAAC;IACN,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;IACf,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC5B,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE;IACjB,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;IAC5C,QAAQ,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,QAAQ,EAAE;CAC9B,CAAC;KACD,MAAM,EAAE;KACR,MAAM,CACL,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,cAAc,KAAK,SAAS,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,KAAK,SAAS,CAAC,EACrF,4CAA4C,CAC7C,CAAC;AAEJ,gFAAgF;AAChF,MAAM,UAAU,WAAW,CAAC,KAAc;IACxC,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,IAAa,EAAE,EAAE,CACnD,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC;QACtD,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC;QACjF,CAAC,CAAC,IAAI,CACT,CAAC;AACJ,CAAC;AACD,gGAAgG;AAChG,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,CAAS,EAAE,CAAS,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAClF,SAAS,IAAI,CAAC,SAAiB,EAAE,KAAc,EAAE,UAAsB;IACrE,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CACvB,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,WAAW,CAAC,KAAK,CAAC,EAAE,GAAG,UAAU,EAAE,CAAC,CAC9E,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;IACxB,IAAI,KAAK,CAAC,MAAM,GAAG,IAAI;QACrB,MAAM,kBAAkB,CAAC,yDAAyD,EAAE;YAClF,MAAM,EAAE,wBAAwB;YAChC,SAAS,EAAE,KAAK;SACjB,CAAC,CAAC;IACL,OAAO,KAAK,CAAC;AACf,CAAC;AACD,SAAS,IAAI,CACX,KAAyB,EACzB,SAAiB,EACjB,KAAc,EACd,IAAiD;IAEjD,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IAC1C,IAAI,CAAC;QACH,IAAI,KAAK,CAAC,MAAM,GAAG,IAAI,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,KAAK,CAAC;YACxD,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC;QAC9C,MAAM,MAAM,GAAG,YAAY,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QAChG,IAAI,MAAM,CAAC,SAAS,KAAK,SAAS,IAAI,MAAM,CAAC,KAAK,KAAK,WAAW,CAAC,KAAK,CAAC;YACvE,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;QAC3C,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC;IACtB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,eAAe,CACnB,oDAAoD,EACpD,EAAE,MAAM,EAAE,gBAAgB,EAAE,SAAS,EAAE,KAAK,EAAE,EAC9C,EAAE,KAAK,EAAE,CACV,CAAC;IACJ,CAAC;AACH,CAAC;AACD,yEAAyE;AACzE,MAAM,UAAU,YAAY,CAAC,SAAiB,EAAE,KAAc,EAAE,cAAsB;IACpF,OAAO,IAAI,CAAC,SAAS,EAAE,KAAK,EAAE,EAAE,cAAc,EAAE,CAAC,CAAC;AACpD,CAAC;AACD,iFAAiF;AACjF,MAAM,UAAU,YAAY,CAC1B,KAAyB,EACzB,SAAiB,EACjB,KAAc;IAEd,OAAO,IAAI,CAAC,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,EAAE,cAAc,EAAE,EAAE,EAAE;QAC1D,IAAI,cAAc,KAAK,SAAS;YAAE,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC;QAC9F,OAAO,cAAc,CAAC;IACxB,CAAC,CAAC,CAAC;AACL,CAAC;AACD,+FAA+F;AAC/F,MAAM,UAAU,oBAAoB,CAAC,SAAiB,EAAE,KAAc,EAAE,QAAiB;IACvF,OAAO,IAAI,CAAC,SAAS,EAAE,KAAK,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC;AAC9C,CAAC;AACD,wFAAwF;AACxF,MAAM,UAAU,oBAAoB,CAClC,KAAyB,EACzB,SAAiB,EACjB,KAAc,EACd,MAAS;IAET,OAAO,IAAI,CAAC,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC;AACjF,CAAC;AACD;;;GAGG;AACH,MAAM,UAAU,YAAY,CAC1B,QAAgB,EAChB,IAAY,EACZ,KAAa,EACb,QAAgB;IAEhB,OAAO,QAAQ,IAAI,mBAAmB,QAAQ,6DAA6D,KAAK,GAAG,QAAQ,CAAC,CAAC,CAAC,uBAAuB,QAAQ,mBAAmB,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC;AAC3L,CAAC;AACD,mFAAmF;AACnF,MAAM,UAAU,YAAY,CAC1B,IAAmB,EACnB,IAAI,GAAwB,IAAI,GAAG,EAAE;IAErC,IAAI,IAAI,KAAK,IAAI;QAAE,OAAO,SAAS,CAAC;IACpC,IAAI,MAAqB,CAAC;IAC1B,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,GAAG,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,YAAY,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAC9D,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,kBAAkB,CACtB,gDAAgD,EAChD,EAAE,MAAM,EAAE,wBAAwB,EAAE,SAAS,EAAE,KAAK,EAAE,EACtD,EAAE,KAAK,EAAE,CACV,CAAC;IACJ,CAAC;IACD,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC;QACrC,MAAM,kBAAkB,CAAC,8DAA8D,EAAE;YACvF,MAAM,EAAE,wBAAwB;YAChC,SAAS,EAAE,KAAK;SACjB,CAAC,CAAC;IACL,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"description-text.d.ts","sourceRoot":"","sources":["../../../src/services/interpro/description-text.ts"],"names":[],"mappings":"AAwBA,gGAAgG;AAChG,wBAAgB,eAAe,CAAC,WAAW,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CA0IxE"}
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Readable projection of InterPro HTML description fragments.
|
|
3
|
+
* @module services/interpro/description-text
|
|
4
|
+
*/
|
|
5
|
+
import { Tokenizer } from 'htmlparser2';
|
|
6
|
+
const PARAGRAPHS = new Set([
|
|
7
|
+
'p',
|
|
8
|
+
'div',
|
|
9
|
+
'section',
|
|
10
|
+
'article',
|
|
11
|
+
'blockquote',
|
|
12
|
+
'pre',
|
|
13
|
+
'h1',
|
|
14
|
+
'h2',
|
|
15
|
+
'h3',
|
|
16
|
+
'h4',
|
|
17
|
+
'h5',
|
|
18
|
+
'h6',
|
|
19
|
+
'table',
|
|
20
|
+
'dl',
|
|
21
|
+
]);
|
|
22
|
+
const REFERENCES = /\b(?:IPR[0-9]{6}|PUB[0-9]+)\b/gi;
|
|
23
|
+
/** Decode description fragments without executing markup or changing the source description. */
|
|
24
|
+
export function descriptionText(description) {
|
|
25
|
+
const fragments = typeof description === 'string'
|
|
26
|
+
? [description]
|
|
27
|
+
: Array.isArray(description)
|
|
28
|
+
? description.flatMap((item) => item && typeof item === 'object' && 'text' in item && typeof item.text === 'string'
|
|
29
|
+
? [item.text]
|
|
30
|
+
: [])
|
|
31
|
+
: [];
|
|
32
|
+
const rendered = fragments
|
|
33
|
+
.map((fragment) => {
|
|
34
|
+
const chunks = [];
|
|
35
|
+
let pending = '';
|
|
36
|
+
let bullet = false;
|
|
37
|
+
let listDepth = 0;
|
|
38
|
+
let suppressed;
|
|
39
|
+
let openingTag = '';
|
|
40
|
+
let attributeName = '';
|
|
41
|
+
let attributeChunks = [];
|
|
42
|
+
let href;
|
|
43
|
+
let anchor;
|
|
44
|
+
const boundary = (separator) => {
|
|
45
|
+
const rank = (value) => value === '\n\n' ? 4 : value === '\n' ? 3 : value === '\t' ? 2 : value === ' ' ? 1 : 0;
|
|
46
|
+
if (rank(separator) > rank(pending))
|
|
47
|
+
pending = separator;
|
|
48
|
+
};
|
|
49
|
+
const open = (name) => {
|
|
50
|
+
if (name === 'script' || name === 'style')
|
|
51
|
+
suppressed = name;
|
|
52
|
+
if (suppressed)
|
|
53
|
+
return;
|
|
54
|
+
if (name === 'a') {
|
|
55
|
+
closeAnchor();
|
|
56
|
+
if (href)
|
|
57
|
+
anchor = { href, text: [] };
|
|
58
|
+
}
|
|
59
|
+
if (name === 'ul' || name === 'ol') {
|
|
60
|
+
if (!listDepth)
|
|
61
|
+
boundary('\n\n');
|
|
62
|
+
listDepth += 1;
|
|
63
|
+
}
|
|
64
|
+
else if (name === 'li') {
|
|
65
|
+
boundary('\n');
|
|
66
|
+
bullet = true;
|
|
67
|
+
}
|
|
68
|
+
else if (PARAGRAPHS.has(name))
|
|
69
|
+
boundary('\n\n');
|
|
70
|
+
else if (name === 'br' || name === 'tr' || name === 'dt' || name === 'dd')
|
|
71
|
+
boundary('\n');
|
|
72
|
+
};
|
|
73
|
+
const append = (value) => {
|
|
74
|
+
if (suppressed)
|
|
75
|
+
return;
|
|
76
|
+
anchor?.text.push(value);
|
|
77
|
+
const normalized = value.replace(/[\t\n\f\r ]+/g, ' ');
|
|
78
|
+
const text = normalized.trim();
|
|
79
|
+
if (text) {
|
|
80
|
+
if (chunks.length)
|
|
81
|
+
chunks.push(pending || (normalized.startsWith(' ') ? ' ' : ''));
|
|
82
|
+
if (bullet)
|
|
83
|
+
chunks.push('- ');
|
|
84
|
+
chunks.push(text);
|
|
85
|
+
pending = normalized.endsWith(' ') ? ' ' : '';
|
|
86
|
+
bullet = false;
|
|
87
|
+
}
|
|
88
|
+
else if (normalized)
|
|
89
|
+
boundary(' ');
|
|
90
|
+
};
|
|
91
|
+
const closeAnchor = () => {
|
|
92
|
+
if (!anchor)
|
|
93
|
+
return;
|
|
94
|
+
const visible = new Set([...anchor.text.join('').matchAll(REFERENCES)].map(([token]) => token.toUpperCase()));
|
|
95
|
+
const references = new Set([...anchor.href.matchAll(REFERENCES)].map(([token]) => token.toUpperCase()));
|
|
96
|
+
anchor = undefined;
|
|
97
|
+
const missing = [...references].filter((token) => !visible.has(token));
|
|
98
|
+
if (missing.length)
|
|
99
|
+
append(` (${missing.join(', ')})`);
|
|
100
|
+
};
|
|
101
|
+
const close = (name) => {
|
|
102
|
+
if (name === suppressed) {
|
|
103
|
+
suppressed = undefined;
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
if (suppressed)
|
|
107
|
+
return;
|
|
108
|
+
if (name === 'a')
|
|
109
|
+
closeAnchor();
|
|
110
|
+
if (name === 'ul' || name === 'ol') {
|
|
111
|
+
listDepth = Math.max(0, listDepth - 1);
|
|
112
|
+
boundary(listDepth ? '\n' : '\n\n');
|
|
113
|
+
}
|
|
114
|
+
else if (name === 'li') {
|
|
115
|
+
bullet = false;
|
|
116
|
+
boundary('\n');
|
|
117
|
+
}
|
|
118
|
+
else if (PARAGRAPHS.has(name))
|
|
119
|
+
boundary('\n\n');
|
|
120
|
+
else if (name === 'tr' || name === 'dt' || name === 'dd')
|
|
121
|
+
boundary('\n');
|
|
122
|
+
else if (name === 'td' || name === 'th')
|
|
123
|
+
boundary('\t');
|
|
124
|
+
};
|
|
125
|
+
/** Token callbacks need no open-element stack; even deeply nested fragments stay streaming. */
|
|
126
|
+
const tokenizer = new Tokenizer({ decodeEntities: true }, {
|
|
127
|
+
onopentagname(start, end) {
|
|
128
|
+
openingTag = fragment.slice(start, end).toLowerCase();
|
|
129
|
+
href = undefined;
|
|
130
|
+
},
|
|
131
|
+
onopentagend() {
|
|
132
|
+
open(openingTag);
|
|
133
|
+
},
|
|
134
|
+
onselfclosingtag() {
|
|
135
|
+
open(openingTag);
|
|
136
|
+
if (openingTag !== 'script' && openingTag !== 'style')
|
|
137
|
+
close(openingTag);
|
|
138
|
+
},
|
|
139
|
+
onclosetag(start, end) {
|
|
140
|
+
close(fragment.slice(start, end).toLowerCase());
|
|
141
|
+
},
|
|
142
|
+
ontext(start, end) {
|
|
143
|
+
append(fragment.slice(start, end));
|
|
144
|
+
},
|
|
145
|
+
ontextentity(codepoint) {
|
|
146
|
+
append(String.fromCodePoint(codepoint));
|
|
147
|
+
},
|
|
148
|
+
onattribdata(start, end) {
|
|
149
|
+
if (attributeName === 'href')
|
|
150
|
+
attributeChunks.push(fragment.slice(start, end));
|
|
151
|
+
},
|
|
152
|
+
onattribentity(codepoint) {
|
|
153
|
+
if (attributeName === 'href')
|
|
154
|
+
attributeChunks.push(String.fromCodePoint(codepoint));
|
|
155
|
+
},
|
|
156
|
+
onattribend() {
|
|
157
|
+
if (attributeName === 'href')
|
|
158
|
+
href = attributeChunks.join('');
|
|
159
|
+
},
|
|
160
|
+
onattribname(start, end) {
|
|
161
|
+
attributeName = fragment.slice(start, end).toLowerCase();
|
|
162
|
+
attributeChunks = [];
|
|
163
|
+
},
|
|
164
|
+
oncdata() { },
|
|
165
|
+
oncomment() { },
|
|
166
|
+
ondeclaration() { },
|
|
167
|
+
onprocessinginstruction() { },
|
|
168
|
+
onend() {
|
|
169
|
+
closeAnchor();
|
|
170
|
+
},
|
|
171
|
+
});
|
|
172
|
+
tokenizer.write(fragment);
|
|
173
|
+
tokenizer.end();
|
|
174
|
+
return chunks.join('');
|
|
175
|
+
})
|
|
176
|
+
.filter(Boolean);
|
|
177
|
+
return rendered.length ? rendered.join('\n\n') : undefined;
|
|
178
|
+
}
|
|
179
|
+
//# sourceMappingURL=description-text.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"description-text.js","sourceRoot":"","sources":["../../../src/services/interpro/description-text.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/** Convert Wikipedia's base64 thumbnail strings to data URIs before constructing either output surface. */
|
|
2
|
+
export declare function normalizeImages<T>(value: T): T;
|
|
3
|
+
/**
|
|
4
|
+
* Keep or drop the base64 `thumbnail` on each Wikipedia page of a detail record. Dropping it
|
|
5
|
+
* removes only that key, so every other page field survives, and the returned notice states
|
|
6
|
+
* what was removed and names `includeThumbnail: true` on `toolName` as the way to get it.
|
|
7
|
+
*/
|
|
8
|
+
export declare function projectWikipediaThumbnails<T extends Record<string, unknown>>(metadata: T, include: boolean, toolName: string): {
|
|
9
|
+
metadata: T;
|
|
10
|
+
notice?: string;
|
|
11
|
+
};
|
|
12
|
+
/** Emit every field losslessly as compact JSON; source text remains inert inside a growing fence. */
|
|
13
|
+
export declare function formatInterpro(value: unknown): {
|
|
14
|
+
type: 'text';
|
|
15
|
+
text: string;
|
|
16
|
+
}[];
|
|
17
|
+
//# sourceMappingURL=format.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../../../src/services/interpro/format.ts"],"names":[],"mappings":"AAyBA,2GAA2G;AAC3G,wBAAgB,eAAe,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,CAAC,CAW9C;AAED;;;;GAIG;AACH,wBAAgB,0BAA0B,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC1E,QAAQ,EAAE,CAAC,EACX,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,MAAM,GACf;IAAE,QAAQ,EAAE,CAAC,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAoBlC;AAED,qGAAqG;AACrG,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,EAAE,CA4D/E"}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Reversible JSON output with usable source URL and image indexes.
|
|
3
|
+
* @module services/interpro/format
|
|
4
|
+
*/
|
|
5
|
+
import { markdown } from '@cyanheads/mcp-ts-core/utils';
|
|
6
|
+
/** Base64 prefixes of the image formats Wikipedia thumbnails arrive in, with their media types. */
|
|
7
|
+
const THUMBNAIL_SIGNATURES = [
|
|
8
|
+
['iVBORw0KGgo', 'image/png'],
|
|
9
|
+
['/9j/', 'image/jpeg'],
|
|
10
|
+
['R0lGOD', 'image/gif'],
|
|
11
|
+
];
|
|
12
|
+
/** The whole string is standard base64, padded only at the end. */
|
|
13
|
+
const BASE64 = /^[A-Za-z0-9+/]+={0,2}$/;
|
|
14
|
+
/** The whole string is a base64 PNG, JPEG, or GIF data URI: the only data URI indexed as an image. */
|
|
15
|
+
const DATA_IMAGE = /^data:image\/(?:png|jpeg|gif);base64,[A-Za-z0-9+/]+={0,2}$/;
|
|
16
|
+
/** An image file extension at the end of a URL path. */
|
|
17
|
+
const IMAGE_PATH = /\.(?:png|jpe?g|gif|webp|svg|avif)$/i;
|
|
18
|
+
function thumbnailDataUri(item) {
|
|
19
|
+
if (!BASE64.test(item))
|
|
20
|
+
return undefined;
|
|
21
|
+
const mediaType = THUMBNAIL_SIGNATURES.find(([prefix]) => item.startsWith(prefix))?.[1];
|
|
22
|
+
return mediaType && `data:${mediaType};base64,${item}`;
|
|
23
|
+
}
|
|
24
|
+
/** Convert Wikipedia's base64 thumbnail strings to data URIs before constructing either output surface. */
|
|
25
|
+
export function normalizeImages(value) {
|
|
26
|
+
if (Array.isArray(value))
|
|
27
|
+
return value.map(normalizeImages);
|
|
28
|
+
if (value && typeof value === 'object')
|
|
29
|
+
return Object.fromEntries(Object.entries(value).map(([key, item]) => [
|
|
30
|
+
key,
|
|
31
|
+
(key === 'thumbnail' && typeof item === 'string' && thumbnailDataUri(item)) ||
|
|
32
|
+
normalizeImages(item),
|
|
33
|
+
]));
|
|
34
|
+
return value;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Keep or drop the base64 `thumbnail` on each Wikipedia page of a detail record. Dropping it
|
|
38
|
+
* removes only that key, so every other page field survives, and the returned notice states
|
|
39
|
+
* what was removed and names `includeThumbnail: true` on `toolName` as the way to get it.
|
|
40
|
+
*/
|
|
41
|
+
export function projectWikipediaThumbnails(metadata, include, toolName) {
|
|
42
|
+
if (include)
|
|
43
|
+
return { metadata };
|
|
44
|
+
let count = 0;
|
|
45
|
+
let bytes = 0;
|
|
46
|
+
const strip = (page) => {
|
|
47
|
+
if (!page || typeof page !== 'object' || Array.isArray(page))
|
|
48
|
+
return page;
|
|
49
|
+
const { thumbnail, ...rest } = page;
|
|
50
|
+
if (typeof thumbnail !== 'string' || thumbnail === '')
|
|
51
|
+
return page;
|
|
52
|
+
count += 1;
|
|
53
|
+
bytes += thumbnail.length;
|
|
54
|
+
return rest;
|
|
55
|
+
};
|
|
56
|
+
const { wikipedia } = metadata;
|
|
57
|
+
const pages = Array.isArray(wikipedia) ? wikipedia.map(strip) : strip(wikipedia);
|
|
58
|
+
if (!count)
|
|
59
|
+
return { metadata };
|
|
60
|
+
const subject = count === 1 ? 'the Wikipedia thumbnail' : `${count} Wikipedia thumbnails`;
|
|
61
|
+
return {
|
|
62
|
+
metadata: { ...metadata, wikipedia: pages },
|
|
63
|
+
notice: `Omitted ${subject} (${bytes.toLocaleString('en-US')} bytes of base64 image data); repeat ${toolName} with includeThumbnail: true to include ${count === 1 ? 'it' : 'them'}.`,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
/** Emit every field losslessly as compact JSON; source text remains inert inside a growing fence. */
|
|
67
|
+
export function formatInterpro(value) {
|
|
68
|
+
const urls = new Set();
|
|
69
|
+
const images = new Set();
|
|
70
|
+
/**
|
|
71
|
+
* Record a parseable URL. A whole-string value whose path has an image extension is also an
|
|
72
|
+
* image; a URL found inside prose is only a link, since clients fetch images unprompted.
|
|
73
|
+
*/
|
|
74
|
+
const addUrl = (candidate, whole) => {
|
|
75
|
+
try {
|
|
76
|
+
const { pathname } = new URL(candidate);
|
|
77
|
+
urls.add(candidate);
|
|
78
|
+
if (whole && IMAGE_PATH.test(pathname))
|
|
79
|
+
images.add(candidate);
|
|
80
|
+
return true;
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
return false;
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
const inspect = (item) => {
|
|
87
|
+
if (typeof item === 'string') {
|
|
88
|
+
if (DATA_IMAGE.test(item)) {
|
|
89
|
+
images.add(item);
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
if (/^https?:\/\//.test(item) && !/[\s\p{Cc}]/u.test(item) && addUrl(item, true))
|
|
93
|
+
return;
|
|
94
|
+
for (const match of item.matchAll(/https?:\/\/[^\s<>"'\p{Cc}]+/gu))
|
|
95
|
+
addUrl(match[0], false);
|
|
96
|
+
}
|
|
97
|
+
else if (Array.isArray(item))
|
|
98
|
+
item.forEach(inspect);
|
|
99
|
+
else if (item && typeof item === 'object')
|
|
100
|
+
Object.values(item).forEach(inspect);
|
|
101
|
+
};
|
|
102
|
+
inspect(value);
|
|
103
|
+
const json = JSON.stringify(value)
|
|
104
|
+
.replace(/\u2028/g, '\\u2028')
|
|
105
|
+
.replace(/\u2029/g, '\\u2029');
|
|
106
|
+
const output = markdown().codeBlock(json, 'json');
|
|
107
|
+
/**
|
|
108
|
+
* CommonMark angle destinations retain parentheses, and entities decode to the original URL.
|
|
109
|
+
* Whitespace and control characters, which no indexed URL holds, are percent-encoded as a
|
|
110
|
+
* backstop so no destination can span a line.
|
|
111
|
+
*/
|
|
112
|
+
const destination = (url) => url
|
|
113
|
+
.replace(/&/g, '&')
|
|
114
|
+
.replace(/</g, '<')
|
|
115
|
+
.replace(/>/g, '>')
|
|
116
|
+
.replace(/\\/g, '\')
|
|
117
|
+
.replace(/[\s\p{Cc}]/gu, encodeURIComponent);
|
|
118
|
+
if (urls.size)
|
|
119
|
+
output
|
|
120
|
+
.raw('\n\nSources and links:\n')
|
|
121
|
+
.raw([...urls].map((url, index) => `[Link ${index + 1}](<${destination(url)}>)`).join('\n\n'));
|
|
122
|
+
if (images.size)
|
|
123
|
+
output
|
|
124
|
+
.raw('\n\nImages:\n')
|
|
125
|
+
.raw([...images]
|
|
126
|
+
.map((url, index) => `}>)`)
|
|
127
|
+
.join('\n\n'));
|
|
128
|
+
return [{ type: 'text', text: output.build() }];
|
|
129
|
+
}
|
|
130
|
+
//# sourceMappingURL=format.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format.js","sourceRoot":"","sources":["../../../src/services/interpro/format.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Bounded HTTP/1.1 adapter for InterPro's malformed bodyless 204 responses.
|
|
3
|
+
* @module services/interpro/http-adapter
|
|
4
|
+
*/
|
|
5
|
+
/** Maximum decoded response size, shared by native and injected transports. */
|
|
6
|
+
export declare const MAX_RESPONSE_BYTES: number;
|
|
7
|
+
/** Fetch-compatible injection seam; callers supply the composed request signal. */
|
|
8
|
+
export type InterproFetch = (url: string, init: RequestInit) => Promise<Response>;
|
|
9
|
+
/** Collect one response without following redirects or retaining malformed connections. */
|
|
10
|
+
export declare const interproHttpFetch: InterproFetch;
|
|
11
|
+
//# sourceMappingURL=http-adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http-adapter.d.ts","sourceRoot":"","sources":["../../../src/services/interpro/http-adapter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAQH,+EAA+E;AAC/E,eAAO,MAAM,kBAAkB,QAAkB,CAAC;AAClD,mFAAmF;AACnF,MAAM,MAAM,aAAa,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;AAElF,2FAA2F;AAC3F,eAAO,MAAM,iBAAiB,EAAE,aAkK5B,CAAC"}
|