@pingroom/sdk 0.7.1 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +144 -12
- package/dist/client.d.ts +67 -18
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +275 -111
- package/dist/client.js.map +1 -1
- package/dist/errors.d.ts +8 -3
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +9 -3
- package/dist/errors.js.map +1 -1
- package/dist/http.d.ts +12 -1
- package/dist/http.d.ts.map +1 -1
- package/dist/http.js +40 -17
- package/dist/http.js.map +1 -1
- package/dist/internal/async.d.ts +2 -0
- package/dist/internal/async.d.ts.map +1 -1
- package/dist/internal/async.js +6 -0
- package/dist/internal/async.js.map +1 -1
- package/dist/internal/guards.d.ts +9 -0
- package/dist/internal/guards.d.ts.map +1 -1
- package/dist/internal/guards.js +21 -0
- package/dist/internal/guards.js.map +1 -1
- package/dist/internal/retry.d.ts +58 -0
- package/dist/internal/retry.d.ts.map +1 -0
- package/dist/internal/retry.js +108 -0
- package/dist/internal/retry.js.map +1 -0
- package/dist/internal/url.d.ts +9 -0
- package/dist/internal/url.d.ts.map +1 -1
- package/dist/internal/url.js +25 -0
- package/dist/internal/url.js.map +1 -1
- package/dist/linkPing.d.ts.map +1 -1
- package/dist/linkPing.js +6 -2
- package/dist/linkPing.js.map +1 -1
- package/dist/mcp.d.ts.map +1 -1
- package/dist/mcp.js +10 -2
- package/dist/mcp.js.map +1 -1
- package/dist/types.d.ts +182 -18
- package/dist/types.d.ts.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/webhooks.d.ts +20 -3
- package/dist/webhooks.d.ts.map +1 -1
- package/dist/webhooks.js +14 -9
- package/dist/webhooks.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { PingRoomError } from '../errors.js';
|
|
2
|
+
/** First retry delay after a transient failure, in ms. */
|
|
3
|
+
export declare const TRANSIENT_BACKOFF_BASE_MS = 1000;
|
|
4
|
+
/** Ceiling on the exponential backoff (a server Retry-After may ask for longer). */
|
|
5
|
+
export declare const TRANSIENT_BACKOFF_CAP_MS = 30000;
|
|
6
|
+
/**
|
|
7
|
+
* How long past the last-seen `expires_at` a wait keeps retrying an
|
|
8
|
+
* unreachable API. The server reports `expired` once expires_at passes, so
|
|
9
|
+
* after this the only outcome left is one that cannot be read. Covers clock
|
|
10
|
+
* skew. Same bound as the CLI.
|
|
11
|
+
*/
|
|
12
|
+
export declare const WAIT_EXPIRY_GRACE_MS: number;
|
|
13
|
+
/** The bound on an unbroken outage while no response has carried `expires_at`. */
|
|
14
|
+
export declare const WAIT_UNKNOWN_EXPIRY_OUTAGE_MS: number;
|
|
15
|
+
/**
|
|
16
|
+
* A failure a read loop may retry: a dropped connection, a request deadline,
|
|
17
|
+
* a 429 (the wait routes share one 30/min bucket per human), or a 5xx.
|
|
18
|
+
* Everything else — 401/403/404/422, a refused redirect, a malformed response —
|
|
19
|
+
* is permanent and must surface to the caller.
|
|
20
|
+
*/
|
|
21
|
+
export declare function isTransientError(error: unknown): error is PingRoomError;
|
|
22
|
+
/**
|
|
23
|
+
* Delay before retrying after the `failures`-th consecutive transient failure:
|
|
24
|
+
* exponential from `baseMs`, capped at 30 s. A server `retryAfter` replaces the
|
|
25
|
+
* exponential step, but is never waited for less than `baseMs`.
|
|
26
|
+
*/
|
|
27
|
+
export declare function transientDelayMs(error: PingRoomError, failures: number, baseMs?: number): number;
|
|
28
|
+
export interface PollUntilSettledOptions<T> {
|
|
29
|
+
/** One bounded long-poll. Its errors are retried only when transient. */
|
|
30
|
+
poll: () => Promise<unknown>;
|
|
31
|
+
/** Check the response's minimal shape; throw `invalid_response` otherwise. */
|
|
32
|
+
validate: (value: unknown) => T;
|
|
33
|
+
/** True once the validated value is terminal. */
|
|
34
|
+
settled: (value: T) => boolean;
|
|
35
|
+
signal?: AbortSignal;
|
|
36
|
+
/** Minimum time between the starts of two polls, in ms. Default 0. */
|
|
37
|
+
minIntervalMs?: number;
|
|
38
|
+
/** Read `expires_at` (an ISO time) from a validated response; it bounds an outage. */
|
|
39
|
+
expiresAt?: (value: T) => unknown;
|
|
40
|
+
/** Names what is waited on in the give-up message, e.g. `approval a1`. */
|
|
41
|
+
what: string;
|
|
42
|
+
/** Called before each retry of a transient failure; `attempt` counts consecutive failures from 1. */
|
|
43
|
+
onRetry?: (error: PingRoomError, attempt: number) => void;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* The shared human-in-the-loop wait loop. Polls until a validated response is
|
|
47
|
+
* terminal; retries transient failures with backoff; rejects with the
|
|
48
|
+
* signal's reason once it aborts. A response that fails validation is never
|
|
49
|
+
* returned as an outcome.
|
|
50
|
+
*
|
|
51
|
+
* The retries are bounded even without a signal. Once only failures have come
|
|
52
|
+
* back since the last valid response, and the last-seen `expires_at` plus
|
|
53
|
+
* {@link WAIT_EXPIRY_GRACE_MS} has passed (or, before any `expires_at` was
|
|
54
|
+
* seen, after {@link WAIT_UNKNOWN_EXPIRY_OUTAGE_MS} of unbroken failures), the
|
|
55
|
+
* wait rejects with `unavailable`, the last failure as its `cause`.
|
|
56
|
+
*/
|
|
57
|
+
export declare function pollUntilSettled<T>(options: PollUntilSettledOptions<T>): Promise<T>;
|
|
58
|
+
//# sourceMappingURL=retry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retry.d.ts","sourceRoot":"","sources":["../../src/internal/retry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAG7C,0DAA0D;AAC1D,eAAO,MAAM,yBAAyB,OAAO,CAAC;AAC9C,oFAAoF;AACpF,eAAO,MAAM,wBAAwB,QAAS,CAAC;AAG/C;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB,QAAa,CAAC;AAC/C,kFAAkF;AAClF,eAAO,MAAM,6BAA6B,QAAc,CAAC;AAEzD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,aAAa,CAQvE;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,aAAa,EACpB,QAAQ,EAAE,MAAM,EAChB,MAAM,GAAE,MAAkC,GACzC,MAAM,CAQR;AAED,MAAM,WAAW,uBAAuB,CAAC,CAAC;IACxC,yEAAyE;IACzE,IAAI,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;IAC7B,8EAA8E;IAC9E,QAAQ,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,CAAC,CAAC;IAChC,iDAAiD;IACjD,OAAO,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,OAAO,CAAC;IAC/B,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,sEAAsE;IACtE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,sFAAsF;IACtF,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,OAAO,CAAC;IAClC,0EAA0E;IAC1E,IAAI,EAAE,MAAM,CAAC;IACb,qGAAqG;IACrG,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CAC3D;AAeD;;;;;;;;;;;GAWG;AACH,wBAAsB,gBAAgB,CAAC,CAAC,EAAE,OAAO,EAAE,uBAAuB,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAyCzF"}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { PingRoomError } from '../errors.js';
|
|
2
|
+
import { sleep, throwIfAborted } from './async.js';
|
|
3
|
+
/** First retry delay after a transient failure, in ms. */
|
|
4
|
+
export const TRANSIENT_BACKOFF_BASE_MS = 1000;
|
|
5
|
+
/** Ceiling on the exponential backoff (a server Retry-After may ask for longer). */
|
|
6
|
+
export const TRANSIENT_BACKOFF_CAP_MS = 30_000;
|
|
7
|
+
/** setTimeout fires immediately above this, so no delay may exceed it. */
|
|
8
|
+
const MAX_TIMER_MS = 2_147_483_647;
|
|
9
|
+
/**
|
|
10
|
+
* How long past the last-seen `expires_at` a wait keeps retrying an
|
|
11
|
+
* unreachable API. The server reports `expired` once expires_at passes, so
|
|
12
|
+
* after this the only outcome left is one that cannot be read. Covers clock
|
|
13
|
+
* skew. Same bound as the CLI.
|
|
14
|
+
*/
|
|
15
|
+
export const WAIT_EXPIRY_GRACE_MS = 5 * 60_000;
|
|
16
|
+
/** The bound on an unbroken outage while no response has carried `expires_at`. */
|
|
17
|
+
export const WAIT_UNKNOWN_EXPIRY_OUTAGE_MS = 15 * 60_000;
|
|
18
|
+
/**
|
|
19
|
+
* A failure a read loop may retry: a dropped connection, a request deadline,
|
|
20
|
+
* a 429 (the wait routes share one 30/min bucket per human), or a 5xx.
|
|
21
|
+
* Everything else — 401/403/404/422, a refused redirect, a malformed response —
|
|
22
|
+
* is permanent and must surface to the caller.
|
|
23
|
+
*/
|
|
24
|
+
export function isTransientError(error) {
|
|
25
|
+
return (error instanceof PingRoomError
|
|
26
|
+
&& (error.code === 'network_error'
|
|
27
|
+
|| error.code === 'timeout'
|
|
28
|
+
|| error.status === 429
|
|
29
|
+
|| error.status >= 500));
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Delay before retrying after the `failures`-th consecutive transient failure:
|
|
33
|
+
* exponential from `baseMs`, capped at 30 s. A server `retryAfter` replaces the
|
|
34
|
+
* exponential step, but is never waited for less than `baseMs`.
|
|
35
|
+
*/
|
|
36
|
+
export function transientDelayMs(error, failures, baseMs = TRANSIENT_BACKOFF_BASE_MS) {
|
|
37
|
+
const base = Number.isFinite(baseMs) && baseMs >= 0 ? baseMs : TRANSIENT_BACKOFF_BASE_MS;
|
|
38
|
+
const retryAfter = error.retryAfter;
|
|
39
|
+
if (typeof retryAfter === 'number' && Number.isFinite(retryAfter) && retryAfter >= 0) {
|
|
40
|
+
return Math.min(MAX_TIMER_MS, Math.max(retryAfter * 1000, base));
|
|
41
|
+
}
|
|
42
|
+
const step = Math.min(Math.max(0, failures - 1), 5);
|
|
43
|
+
return Math.min(MAX_TIMER_MS, Math.max(base, TRANSIENT_BACKOFF_CAP_MS), base * 2 ** step);
|
|
44
|
+
}
|
|
45
|
+
function timeOf(value) {
|
|
46
|
+
const at = typeof value === 'string' ? Date.parse(value) : NaN;
|
|
47
|
+
return Number.isFinite(at) ? at : null;
|
|
48
|
+
}
|
|
49
|
+
function unavailable(last, since, what) {
|
|
50
|
+
const reason = last.status > 0 ? `HTTP ${last.status}` : (last.code ?? 'network error');
|
|
51
|
+
return new PingRoomError(`PingRoom unavailable since ${new Date(since).toISOString()} (${reason}); stopped waiting for ${what}.`, { code: 'unavailable', cause: last });
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* The shared human-in-the-loop wait loop. Polls until a validated response is
|
|
55
|
+
* terminal; retries transient failures with backoff; rejects with the
|
|
56
|
+
* signal's reason once it aborts. A response that fails validation is never
|
|
57
|
+
* returned as an outcome.
|
|
58
|
+
*
|
|
59
|
+
* The retries are bounded even without a signal. Once only failures have come
|
|
60
|
+
* back since the last valid response, and the last-seen `expires_at` plus
|
|
61
|
+
* {@link WAIT_EXPIRY_GRACE_MS} has passed (or, before any `expires_at` was
|
|
62
|
+
* seen, after {@link WAIT_UNKNOWN_EXPIRY_OUTAGE_MS} of unbroken failures), the
|
|
63
|
+
* wait rejects with `unavailable`, the last failure as its `cause`.
|
|
64
|
+
*/
|
|
65
|
+
export async function pollUntilSettled(options) {
|
|
66
|
+
const { poll, validate, settled, signal, minIntervalMs = 0, expiresAt, what, onRetry } = options;
|
|
67
|
+
let failures = 0;
|
|
68
|
+
let failingSince = null;
|
|
69
|
+
// expires_at plus grace, from the last valid response that carried one.
|
|
70
|
+
let deadline = null;
|
|
71
|
+
for (;;) {
|
|
72
|
+
throwIfAborted(signal);
|
|
73
|
+
const startedAt = Date.now();
|
|
74
|
+
let value;
|
|
75
|
+
try {
|
|
76
|
+
value = validate(await poll());
|
|
77
|
+
}
|
|
78
|
+
catch (error) {
|
|
79
|
+
throwIfAborted(signal);
|
|
80
|
+
if (!isTransientError(error)) {
|
|
81
|
+
throw error;
|
|
82
|
+
}
|
|
83
|
+
failures += 1;
|
|
84
|
+
failingSince ??= Date.now();
|
|
85
|
+
const remaining = (deadline ?? failingSince + WAIT_UNKNOWN_EXPIRY_OUTAGE_MS) - Date.now();
|
|
86
|
+
if (remaining <= 0) {
|
|
87
|
+
throw unavailable(error, failingSince, what);
|
|
88
|
+
}
|
|
89
|
+
onRetry?.(error, failures);
|
|
90
|
+
// Never sleep past the bound: the last attempt lands on it, not after it.
|
|
91
|
+
await sleep(Math.min(transientDelayMs(error, failures), remaining), signal);
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
failures = 0;
|
|
95
|
+
failingSince = null;
|
|
96
|
+
const expiry = expiresAt ? timeOf(expiresAt(value)) : null;
|
|
97
|
+
if (expiry !== null) {
|
|
98
|
+
deadline = expiry + WAIT_EXPIRY_GRACE_MS;
|
|
99
|
+
}
|
|
100
|
+
if (settled(value)) {
|
|
101
|
+
return value;
|
|
102
|
+
}
|
|
103
|
+
// An injected transport can resolve pending polls immediately. Yield
|
|
104
|
+
// between them so timer-driven cancellation and deadlines can run.
|
|
105
|
+
await sleep(Math.max(0, minIntervalMs - (Date.now() - startedAt)), signal);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
//# sourceMappingURL=retry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retry.js","sourceRoot":"","sources":["../../src/internal/retry.ts"],"names":[],"mappings":"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"}
|
package/dist/internal/url.d.ts
CHANGED
|
@@ -12,4 +12,13 @@ export declare function assertSecureUrl(rawUrl: string, allowInsecure: boolean):
|
|
|
12
12
|
* errors, so a message copied from one must not reach a caller's logs as-is.
|
|
13
13
|
*/
|
|
14
14
|
export declare function redactUrlInMessage(message: string, url: URL, rawUrl: string): string;
|
|
15
|
+
/**
|
|
16
|
+
* Every request goes out with `redirect: 'manual'` (Cloudflare Workers throw
|
|
17
|
+
* on `'error'`), so a redirect comes back as a response instead of being
|
|
18
|
+
* followed. Refuse it: a 307/308 would replay pairing secrets, uploaded bytes
|
|
19
|
+
* or a webhook body to whatever origin `Location` names. Browsers report a
|
|
20
|
+
* manual redirect as an `opaqueredirect` with status 0; other runtimes return
|
|
21
|
+
* the 3xx itself.
|
|
22
|
+
*/
|
|
23
|
+
export declare function refuseRedirect(res: Response): void;
|
|
15
24
|
//# sourceMappingURL=url.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"url.d.ts","sourceRoot":"","sources":["../../src/internal/url.ts"],"names":[],"mappings":"AAEA,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAGxD;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,OAAO,GAAG,GAAG,CAsB3E;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAUpF"}
|
|
1
|
+
{"version":3,"file":"url.d.ts","sourceRoot":"","sources":["../../src/internal/url.ts"],"names":[],"mappings":"AAEA,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAGxD;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,OAAO,GAAG,GAAG,CAsB3E;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAUpF;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,QAAQ,GAAG,IAAI,CAelD"}
|
package/dist/internal/url.js
CHANGED
|
@@ -48,4 +48,29 @@ export function redactUrlInMessage(message, url, rawUrl) {
|
|
|
48
48
|
}
|
|
49
49
|
return out;
|
|
50
50
|
}
|
|
51
|
+
/**
|
|
52
|
+
* Every request goes out with `redirect: 'manual'` (Cloudflare Workers throw
|
|
53
|
+
* on `'error'`), so a redirect comes back as a response instead of being
|
|
54
|
+
* followed. Refuse it: a 307/308 would replay pairing secrets, uploaded bytes
|
|
55
|
+
* or a webhook body to whatever origin `Location` names. Browsers report a
|
|
56
|
+
* manual redirect as an `opaqueredirect` with status 0; other runtimes return
|
|
57
|
+
* the 3xx itself.
|
|
58
|
+
*/
|
|
59
|
+
export function refuseRedirect(res) {
|
|
60
|
+
if (res.type === 'opaqueredirect' || (res.status >= 300 && res.status < 400)) {
|
|
61
|
+
// Release the body, best effort. A custom `fetch` such as node-fetch hands
|
|
62
|
+
// back a Node Readable with no cancel(); calling it threw a TypeError that
|
|
63
|
+
// surfaced as a retryable network_error instead of this refusal.
|
|
64
|
+
try {
|
|
65
|
+
res.body?.cancel?.()?.catch?.(() => { });
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
// Ignored: the refusal below is what matters.
|
|
69
|
+
}
|
|
70
|
+
throw new PingRoomError('Refusing to follow a redirect; credentials and request bodies are never forwarded.', {
|
|
71
|
+
code: 'redirect_refused',
|
|
72
|
+
status: res.status,
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
}
|
|
51
76
|
//# sourceMappingURL=url.js.map
|
package/dist/internal/url.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"url.js","sourceRoot":"","sources":["../../src/internal/url.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAE7C,MAAM,UAAU,cAAc,CAAC,QAAgB;IAC7C,MAAM,CAAC,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IACvE,OAAO,CAAC,KAAK,WAAW,IAAI,CAAC,KAAK,WAAW,IAAI,CAAC,KAAK,KAAK,IAAI,CAAC,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC;AAC3F,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAAC,MAAc,EAAE,aAAsB;IACpE,IAAI,GAAQ,CAAC;IACb,IAAI,CAAC;QACH,GAAG,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC;IACxB,CAAC;IAAC,MAAM,CAAC;QACP,0EAA0E;QAC1E,2CAA2C;QAC3C,MAAM,IAAI,aAAa,CAAC,+DAA+D,EAAE;YACvF,IAAI,EAAE,aAAa;SACpB,CAAC,CAAC;IACL,CAAC;IACD,IAAI,GAAG,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAC9B,OAAO,GAAG,CAAC;IACb,CAAC;IACD,IAAI,GAAG,CAAC,QAAQ,KAAK,OAAO,IAAI,CAAC,aAAa,IAAI,cAAc,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC;QAChF,OAAO,GAAG,CAAC;IACb,CAAC;IACD,MAAM,IAAI,aAAa,CACrB,sDAAsD,GAAG,CAAC,QAAQ,KAAK,GAAG,CAAC,IAAI,KAAK;QAClF,sEAAsE,EACxE,EAAE,IAAI,EAAE,cAAc,EAAE,CACzB,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,kBAAkB,CAAC,OAAe,EAAE,GAAQ,EAAE,MAAc;IAC1E,MAAM,QAAQ,GAAG,GAAG,GAAG,CAAC,MAAM,aAAa,CAAC;IAC5C,IAAI,GAAG,GAAG,OAAO,CAAC;IAClB,KAAK,MAAM,IAAI,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;QACtC,IAAI,IAAI;YAAE,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACjD,CAAC;IACD,KAAK,MAAM,IAAI,IAAI,CAAC,GAAG,GAAG,CAAC,QAAQ,GAAG,GAAG,CAAC,MAAM,GAAG,GAAG,CAAC,IAAI,EAAE,EAAE,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC7E,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC;YAAE,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IACjE,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
|
|
1
|
+
{"version":3,"file":"url.js","sourceRoot":"","sources":["../../src/internal/url.ts"],"names":[],"mappings":"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"}
|
package/dist/linkPing.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"linkPing.d.ts","sourceRoot":"","sources":["../src/linkPing.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,MAAM,WAAW,aAAa;IAC5B,2FAA2F;IAC3F,GAAG,EAAE,MAAM,CAAC;IACZ,oFAAoF;IACpF,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;
|
|
1
|
+
{"version":3,"file":"linkPing.d.ts","sourceRoot":"","sources":["../src/linkPing.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,MAAM,WAAW,aAAa;IAC5B,2FAA2F;IAC3F,GAAG,EAAE,MAAM,CAAC;IACZ,oFAAoF;IACpF,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAUD,wFAAwF;AACxF,wBAAgB,QAAQ,CAAC,KAAK,EAAE,aAAa,GAAG,YAAY,CAmB3D"}
|
package/dist/linkPing.js
CHANGED
|
@@ -13,6 +13,10 @@
|
|
|
13
13
|
*/
|
|
14
14
|
const URL_MAX = 2048;
|
|
15
15
|
const LABEL_MAX = 26;
|
|
16
|
+
/** Count code points, as the server's mb_strlen does — an emoji is one character, not two. */
|
|
17
|
+
function characterLength(value) {
|
|
18
|
+
return Array.from(value).length;
|
|
19
|
+
}
|
|
16
20
|
/** Build the `data` fragment for a link ping. Spread it into a ping's `data` object. */
|
|
17
21
|
export function linkPing(input) {
|
|
18
22
|
let parsed;
|
|
@@ -25,10 +29,10 @@ export function linkPing(input) {
|
|
|
25
29
|
if (parsed.protocol !== 'https:' && parsed.protocol !== 'http:') {
|
|
26
30
|
throw new TypeError('linkPing: url must be an absolute http(s) URL');
|
|
27
31
|
}
|
|
28
|
-
if (input.url
|
|
32
|
+
if (characterLength(input.url) > URL_MAX) {
|
|
29
33
|
throw new TypeError(`linkPing: url must be at most ${URL_MAX} characters`);
|
|
30
34
|
}
|
|
31
|
-
if (input.buttonLabel !== undefined && input.buttonLabel
|
|
35
|
+
if (input.buttonLabel !== undefined && characterLength(input.buttonLabel) > LABEL_MAX) {
|
|
32
36
|
throw new TypeError(`linkPing: buttonLabel must be at most ${LABEL_MAX} characters`);
|
|
33
37
|
}
|
|
34
38
|
const out = { url: input.url };
|
package/dist/linkPing.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"linkPing.js","sourceRoot":"","sources":["../src/linkPing.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAeH,MAAM,OAAO,GAAG,IAAI,CAAC;AACrB,MAAM,SAAS,GAAG,EAAE,CAAC;AAErB,wFAAwF;AACxF,MAAM,UAAU,QAAQ,CAAC,KAAoB;IAC3C,IAAI,MAAW,CAAC;IAChB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC9B,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,SAAS,CAAC,kCAAkC,CAAC,CAAC;IAC1D,CAAC;IACD,IAAI,MAAM,CAAC,QAAQ,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;QAChE,MAAM,IAAI,SAAS,CAAC,+CAA+C,CAAC,CAAC;IACvE,CAAC;IACD,IAAI,KAAK,CAAC,GAAG,CAAC,
|
|
1
|
+
{"version":3,"file":"linkPing.js","sourceRoot":"","sources":["../src/linkPing.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAeH,MAAM,OAAO,GAAG,IAAI,CAAC;AACrB,MAAM,SAAS,GAAG,EAAE,CAAC;AAErB,8FAA8F;AAC9F,SAAS,eAAe,CAAC,KAAa;IACpC,OAAO,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC;AAClC,CAAC;AAED,wFAAwF;AACxF,MAAM,UAAU,QAAQ,CAAC,KAAoB;IAC3C,IAAI,MAAW,CAAC;IAChB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC9B,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,SAAS,CAAC,kCAAkC,CAAC,CAAC;IAC1D,CAAC;IACD,IAAI,MAAM,CAAC,QAAQ,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;QAChE,MAAM,IAAI,SAAS,CAAC,+CAA+C,CAAC,CAAC;IACvE,CAAC;IACD,IAAI,eAAe,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,OAAO,EAAE,CAAC;QACzC,MAAM,IAAI,SAAS,CAAC,iCAAiC,OAAO,aAAa,CAAC,CAAC;IAC7E,CAAC;IACD,IAAI,KAAK,CAAC,WAAW,KAAK,SAAS,IAAI,eAAe,CAAC,KAAK,CAAC,WAAW,CAAC,GAAG,SAAS,EAAE,CAAC;QACtF,MAAM,IAAI,SAAS,CAAC,yCAAyC,SAAS,aAAa,CAAC,CAAC;IACvF,CAAC;IACD,MAAM,GAAG,GAAiB,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,EAAE,CAAC;IAC7C,IAAI,KAAK,CAAC,WAAW,KAAK,SAAS;QAAE,GAAG,CAAC,YAAY,GAAG,KAAK,CAAC,WAAW,CAAC;IAC1E,OAAO,GAAG,CAAC;AACb,CAAC"}
|
package/dist/mcp.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcp.d.ts","sourceRoot":"","sources":["../src/mcp.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAG5C,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACtC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,CAAC,CAAC;IACxE,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,mBAAmB;IAClC,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACtC,UAAU,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,CAAC;IACtE,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED;;;;GAIG;AACH,qBAAa,SAAS;IAOlB,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,OAAO,CAAC,QAAQ,CAAC,IAAI;IAPvB,OAAO,CAAC,MAAM,CAAK;IACnB,OAAO,CAAC,cAAc,CAA6C;IACnE,OAAO,CAAC,gBAAgB,CAAoC;IAC5D,OAAO,CAAC,eAAe,CAAuB;gBAG3B,IAAI,EAAE,UAAU,EAChB,IAAI,SAAmB;IAG1C,4FAA4F;IACtF,IAAI,CAAC,CAAC,GAAG,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"mcp.d.ts","sourceRoot":"","sources":["../src/mcp.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAG5C,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACtC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,CAAC,CAAC;IACxE,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,mBAAmB;IAClC,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACtC,UAAU,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,CAAC;IACtE,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED;;;;GAIG;AACH,qBAAa,SAAS;IAOlB,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,OAAO,CAAC,QAAQ,CAAC,IAAI;IAPvB,OAAO,CAAC,MAAM,CAAK;IACnB,OAAO,CAAC,cAAc,CAA6C;IACnE,OAAO,CAAC,gBAAgB,CAAoC;IAC5D,OAAO,CAAC,eAAe,CAAuB;gBAG3B,IAAI,EAAE,UAAU,EAChB,IAAI,SAAmB;IAG1C,4FAA4F;IACtF,IAAI,CAAC,CAAC,GAAG,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAwBrF;;;OAGG;IACH,UAAU,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAc1E,gFAAgF;IAChF,OAAO,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAIjE,SAAS,IAAI,OAAO,CAAC;QAAE,KAAK,EAAE,OAAO,EAAE,CAAA;KAAE,CAAC;IAK1C,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GAAG,OAAO,CAAC,aAAa,CAAC;YAK1E,iBAAiB;YAsBjB,MAAM;IAQpB,OAAO,CAAC,OAAO;CAMhB"}
|
package/dist/mcp.js
CHANGED
|
@@ -24,13 +24,21 @@ export class McpClient {
|
|
|
24
24
|
body: envelope,
|
|
25
25
|
headers: this.headers(),
|
|
26
26
|
});
|
|
27
|
-
|
|
27
|
+
const isObject = res !== null && typeof res === 'object' && !Array.isArray(res);
|
|
28
|
+
if (isObject && res.error) {
|
|
28
29
|
throw new PingRoomError(`MCP error ${res.error.code}: ${res.error.message}`, {
|
|
29
30
|
code: `mcp_${res.error.code}`,
|
|
30
31
|
body: res.error,
|
|
31
32
|
});
|
|
32
33
|
}
|
|
33
|
-
|
|
34
|
+
// A 2xx that is not a JSON-RPC response (no body, an HTML page, an object
|
|
35
|
+
// with neither member) must fail here, not as a TypeError in the caller.
|
|
36
|
+
if (!isObject || !Object.prototype.hasOwnProperty.call(res, 'result')) {
|
|
37
|
+
throw new PingRoomError('MCP endpoint returned a response with neither `result` nor `error`.', {
|
|
38
|
+
code: 'mcp_invalid_response',
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
return res.result;
|
|
34
42
|
}
|
|
35
43
|
/**
|
|
36
44
|
* Perform the MCP initialize handshake once, including the required
|
package/dist/mcp.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcp.js","sourceRoot":"","sources":["../src/mcp.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AA4BvC;;;;GAIG;AACH,MAAM,OAAO,SAAS;IAOD;IACA;IAPX,MAAM,GAAG,CAAC,CAAC;IACX,cAAc,GAAwC,IAAI,CAAC;IAC3D,gBAAgB,GAA+B,IAAI,CAAC;IACpD,eAAe,GAAkB,IAAI,CAAC;IAE9C,YACmB,IAAgB,EAChB,OAAO,gBAAgB;QADvB,SAAI,GAAJ,IAAI,CAAY;QAChB,SAAI,GAAJ,IAAI,CAAmB;IACvC,CAAC;IAEJ,4FAA4F;IAC5F,KAAK,CAAC,IAAI,CAAc,MAAc,EAAE,MAAgC;QACtE,MAAM,EAAE,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;QACzB,MAAM,QAAQ,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;QAC/E,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,CAAuC,MAAM,EAAE,IAAI,CAAC,IAAI,EAAE;YAC3F,IAAI,EAAE,QAAQ;YACd,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE;SACxB,CAAC,CAAC;QACH,IAAI,GAAG,IAAI,GAAG,CAAC,KAAK,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"mcp.js","sourceRoot":"","sources":["../src/mcp.ts"],"names":[],"mappings":"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"}
|