@ttctl/core 0.0.0 → 0.1.0-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +49 -9
- package/dist/__generated__/gateway.d.ts +4546 -0
- package/dist/__generated__/gateway.d.ts.map +1 -0
- package/dist/__generated__/gateway.js +9 -0
- package/dist/__generated__/gateway.js.map +1 -0
- package/dist/__generated__/talent-profile-zod-schemas.d.ts +1187 -0
- package/dist/__generated__/talent-profile-zod-schemas.d.ts.map +1 -0
- package/dist/__generated__/talent-profile-zod-schemas.js +1136 -0
- package/dist/__generated__/talent-profile-zod-schemas.js.map +1 -0
- package/dist/__generated__/talent-profile.d.ts +1397 -0
- package/dist/__generated__/talent-profile.d.ts.map +1 -0
- package/dist/__generated__/talent-profile.js +9 -0
- package/dist/__generated__/talent-profile.js.map +1 -0
- package/dist/__generated__/zod-schemas.d.ts +2895 -0
- package/dist/__generated__/zod-schemas.d.ts.map +1 -0
- package/dist/__generated__/zod-schemas.js +3121 -0
- package/dist/__generated__/zod-schemas.js.map +1 -0
- package/dist/__tests__/fixtures/profile/builders.d.ts +74 -0
- package/dist/__tests__/fixtures/profile/builders.d.ts.map +1 -0
- package/dist/__tests__/fixtures/profile/builders.js +196 -0
- package/dist/__tests__/fixtures/profile/builders.js.map +1 -0
- package/dist/__tests__/fixtures/profile/data.d.ts +39 -0
- package/dist/__tests__/fixtures/profile/data.d.ts.map +1 -0
- package/dist/__tests__/fixtures/profile/data.js +230 -0
- package/dist/__tests__/fixtures/profile/data.js.map +1 -0
- package/dist/__tests__/fixtures/profile/index.d.ts +9 -0
- package/dist/__tests__/fixtures/profile/index.d.ts.map +1 -0
- package/dist/__tests__/fixtures/profile/index.js +10 -0
- package/dist/__tests__/fixtures/profile/index.js.map +1 -0
- package/dist/__tests__/fixtures/profile/types.d.ts +53 -0
- package/dist/__tests__/fixtures/profile/types.d.ts.map +1 -0
- package/dist/__tests__/fixtures/profile/types.js +4 -0
- package/dist/__tests__/fixtures/profile/types.js.map +1 -0
- package/dist/auth/errors.d.ts +82 -0
- package/dist/auth/errors.d.ts.map +1 -0
- package/dist/auth/errors.js +68 -0
- package/dist/auth/errors.js.map +1 -0
- package/dist/auth.d.ts +192 -0
- package/dist/auth.d.ts.map +1 -0
- package/dist/auth.js +294 -0
- package/dist/auth.js.map +1 -0
- package/dist/config.d.ts +212 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +349 -0
- package/dist/config.js.map +1 -0
- package/dist/configLock.d.ts +50 -0
- package/dist/configLock.d.ts.map +1 -0
- package/dist/configLock.js +88 -0
- package/dist/configLock.js.map +1 -0
- package/dist/configWriter.d.ts +97 -0
- package/dist/configWriter.d.ts.map +1 -0
- package/dist/configWriter.js +687 -0
- package/dist/configWriter.js.map +1 -0
- package/dist/index.d.ts +37 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +28 -0
- package/dist/index.js.map +1 -0
- package/dist/kill-switch.d.ts +161 -0
- package/dist/kill-switch.d.ts.map +1 -0
- package/dist/kill-switch.js +235 -0
- package/dist/kill-switch.js.map +1 -0
- package/dist/lib/date.d.ts +58 -0
- package/dist/lib/date.d.ts.map +1 -0
- package/dist/lib/date.js +104 -0
- package/dist/lib/date.js.map +1 -0
- package/dist/lib/diagnostic-log.d.ts +159 -0
- package/dist/lib/diagnostic-log.d.ts.map +1 -0
- package/dist/lib/diagnostic-log.js +186 -0
- package/dist/lib/diagnostic-log.js.map +1 -0
- package/dist/lib/package-version.d.ts +19 -0
- package/dist/lib/package-version.d.ts.map +1 -0
- package/dist/lib/package-version.js +38 -0
- package/dist/lib/package-version.js.map +1 -0
- package/dist/lib/redact.d.ts +153 -0
- package/dist/lib/redact.d.ts.map +1 -0
- package/dist/lib/redact.js +207 -0
- package/dist/lib/redact.js.map +1 -0
- package/dist/lib/text.d.ts +14 -0
- package/dist/lib/text.d.ts.map +1 -0
- package/dist/lib/text.js +21 -0
- package/dist/lib/text.js.map +1 -0
- package/dist/lib/wire-shape.d.ts +131 -0
- package/dist/lib/wire-shape.d.ts.map +1 -0
- package/dist/lib/wire-shape.js +376 -0
- package/dist/lib/wire-shape.js.map +1 -0
- package/dist/onepassword.d.ts +29 -0
- package/dist/onepassword.d.ts.map +1 -0
- package/dist/onepassword.js +112 -0
- package/dist/onepassword.js.map +1 -0
- package/dist/services/_shared/transport.d.ts +148 -0
- package/dist/services/_shared/transport.d.ts.map +1 -0
- package/dist/services/_shared/transport.js +102 -0
- package/dist/services/_shared/transport.js.map +1 -0
- package/dist/services/applications/index.d.ts +210 -0
- package/dist/services/applications/index.d.ts.map +1 -0
- package/dist/services/applications/index.js +240 -0
- package/dist/services/applications/index.js.map +1 -0
- package/dist/services/availability/index.d.ts +254 -0
- package/dist/services/availability/index.d.ts.map +1 -0
- package/dist/services/availability/index.js +310 -0
- package/dist/services/availability/index.js.map +1 -0
- package/dist/services/contracts/index.d.ts +132 -0
- package/dist/services/contracts/index.d.ts.map +1 -0
- package/dist/services/contracts/index.js +211 -0
- package/dist/services/contracts/index.js.map +1 -0
- package/dist/services/engagements/index.d.ts +504 -0
- package/dist/services/engagements/index.d.ts.map +1 -0
- package/dist/services/engagements/index.js +613 -0
- package/dist/services/engagements/index.js.map +1 -0
- package/dist/services/jobs/index.d.ts +490 -0
- package/dist/services/jobs/index.d.ts.map +1 -0
- package/dist/services/jobs/index.js +753 -0
- package/dist/services/jobs/index.js.map +1 -0
- package/dist/services/payments/index.d.ts +415 -0
- package/dist/services/payments/index.d.ts.map +1 -0
- package/dist/services/payments/index.js +636 -0
- package/dist/services/payments/index.js.map +1 -0
- package/dist/services/profile/__tests__/fixtures.d.ts +214 -0
- package/dist/services/profile/__tests__/fixtures.d.ts.map +1 -0
- package/dist/services/profile/__tests__/fixtures.js +176 -0
- package/dist/services/profile/__tests__/fixtures.js.map +1 -0
- package/dist/services/profile/basic/index.d.ts +390 -0
- package/dist/services/profile/basic/index.d.ts.map +1 -0
- package/dist/services/profile/basic/index.js +1007 -0
- package/dist/services/profile/basic/index.js.map +1 -0
- package/dist/services/profile/certifications/index.d.ts +74 -0
- package/dist/services/profile/certifications/index.d.ts.map +1 -0
- package/dist/services/profile/certifications/index.js +169 -0
- package/dist/services/profile/certifications/index.js.map +1 -0
- package/dist/services/profile/education/index.d.ts +73 -0
- package/dist/services/profile/education/index.d.ts.map +1 -0
- package/dist/services/profile/education/index.js +168 -0
- package/dist/services/profile/education/index.js.map +1 -0
- package/dist/services/profile/employment/index.d.ts +111 -0
- package/dist/services/profile/employment/index.d.ts.map +1 -0
- package/dist/services/profile/employment/index.js +202 -0
- package/dist/services/profile/employment/index.js.map +1 -0
- package/dist/services/profile/external/index.d.ts +219 -0
- package/dist/services/profile/external/index.d.ts.map +1 -0
- package/dist/services/profile/external/index.js +560 -0
- package/dist/services/profile/external/index.js.map +1 -0
- package/dist/services/profile/index.d.ts +24 -0
- package/dist/services/profile/index.d.ts.map +1 -0
- package/dist/services/profile/index.js +26 -0
- package/dist/services/profile/index.js.map +1 -0
- package/dist/services/profile/industries/index.d.ts +130 -0
- package/dist/services/profile/industries/index.d.ts.map +1 -0
- package/dist/services/profile/industries/index.js +292 -0
- package/dist/services/profile/industries/index.js.map +1 -0
- package/dist/services/profile/portfolio/index.d.ts +352 -0
- package/dist/services/profile/portfolio/index.d.ts.map +1 -0
- package/dist/services/profile/portfolio/index.js +833 -0
- package/dist/services/profile/portfolio/index.js.map +1 -0
- package/dist/services/profile/resume/index.d.ts +60 -0
- package/dist/services/profile/resume/index.d.ts.map +1 -0
- package/dist/services/profile/resume/index.js +212 -0
- package/dist/services/profile/resume/index.js.map +1 -0
- package/dist/services/profile/reviews/index.d.ts +137 -0
- package/dist/services/profile/reviews/index.d.ts.map +1 -0
- package/dist/services/profile/reviews/index.js +431 -0
- package/dist/services/profile/reviews/index.js.map +1 -0
- package/dist/services/profile/shared.d.ts +127 -0
- package/dist/services/profile/shared.d.ts.map +1 -0
- package/dist/services/profile/shared.js +155 -0
- package/dist/services/profile/shared.js.map +1 -0
- package/dist/services/profile/skills/index.d.ts +212 -0
- package/dist/services/profile/skills/index.d.ts.map +1 -0
- package/dist/services/profile/skills/index.js +461 -0
- package/dist/services/profile/skills/index.js.map +1 -0
- package/dist/services/profile/visas/index.d.ts +74 -0
- package/dist/services/profile/visas/index.d.ts.map +1 -0
- package/dist/services/profile/visas/index.js +306 -0
- package/dist/services/profile/visas/index.js.map +1 -0
- package/dist/services/timesheet/index.d.ts +326 -0
- package/dist/services/timesheet/index.d.ts.map +1 -0
- package/dist/services/timesheet/index.js +324 -0
- package/dist/services/timesheet/index.js.map +1 -0
- package/dist/services/translations.d.ts +79 -0
- package/dist/services/translations.d.ts.map +1 -0
- package/dist/services/translations.js +136 -0
- package/dist/services/translations.js.map +1 -0
- package/dist/transport-resilience.d.ts +136 -0
- package/dist/transport-resilience.d.ts.map +1 -0
- package/dist/transport-resilience.js +247 -0
- package/dist/transport-resilience.js.map +1 -0
- package/dist/transport.d.ts +408 -0
- package/dist/transport.d.ts.map +1 -0
- package/dist/transport.js +691 -0
- package/dist/transport.js.map +1 -0
- package/dist/types.d.ts +41 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +18 -0
- package/dist/types.js.map +1 -0
- package/package.json +40 -12
- package/index.js +0 -7
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { TtctlError } from "./auth/errors.js";
|
|
2
|
+
import type { ToptalSurface } from "./types.js";
|
|
3
|
+
/**
|
|
4
|
+
* Final-failure transport error raised after all retries are exhausted or
|
|
5
|
+
* when a fatal signal-driven condition (caller abort, internal timeout)
|
|
6
|
+
* terminates the request loop.
|
|
7
|
+
*
|
|
8
|
+
* Extends {@link TtctlError} so it propagates through service callers'
|
|
9
|
+
* `if (err instanceof TtctlError) throw err;` guard verbatim — surfaces
|
|
10
|
+
* (CLI / MCP) render `error.recovery` directly.
|
|
11
|
+
*
|
|
12
|
+
* **Codes**:
|
|
13
|
+
*
|
|
14
|
+
* - `TIMEOUT` — internal per-request timeout fired (default 30s,
|
|
15
|
+
* overridable via `TTCTL_TRANSPORT_TIMEOUT_MS`). The
|
|
16
|
+
* underlying socket/handshake never completed in time.
|
|
17
|
+
* - `ABORTED` — caller's `AbortSignal` aborted before the request
|
|
18
|
+
* completed. Typically driven by the MCP client cancelling
|
|
19
|
+
* an in-flight tool call.
|
|
20
|
+
* - `RATE_LIMITED` — HTTP 429 returned by the surface and the retry budget
|
|
21
|
+
* was exhausted. `lastRetryAfterMs` (when set) reports
|
|
22
|
+
* the server's last `Retry-After` hint.
|
|
23
|
+
* - `SERVER_ERROR` — HTTP 5xx returned by the surface and the retry budget
|
|
24
|
+
* was exhausted.
|
|
25
|
+
*/
|
|
26
|
+
export declare class TransportError extends TtctlError {
|
|
27
|
+
readonly surface: ToptalSurface;
|
|
28
|
+
readonly endpoint: string;
|
|
29
|
+
readonly attempts: number;
|
|
30
|
+
readonly lastStatus?: number | undefined;
|
|
31
|
+
readonly lastRetryAfterMs?: number | undefined;
|
|
32
|
+
readonly name = "TransportError";
|
|
33
|
+
readonly code: "TIMEOUT" | "ABORTED" | "RATE_LIMITED" | "SERVER_ERROR";
|
|
34
|
+
readonly recovery: string;
|
|
35
|
+
constructor(code: "TIMEOUT" | "ABORTED" | "RATE_LIMITED" | "SERVER_ERROR", surface: ToptalSurface, endpoint: string, attempts: number, message: string, lastStatus?: number | undefined, lastRetryAfterMs?: number | undefined, options?: {
|
|
36
|
+
cause?: unknown;
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Transport resilience configuration. All fields are read from environment
|
|
41
|
+
* variables ONCE on first call to {@link readTransportConfig} and cached. The
|
|
42
|
+
* cache is reset by {@link resetTransportConfigCache} (test-only).
|
|
43
|
+
*
|
|
44
|
+
* Env-var resolution:
|
|
45
|
+
*
|
|
46
|
+
* | Field | Env var | Default | Bounds |
|
|
47
|
+
* |----------------|--------------------------------------|---------|----------|
|
|
48
|
+
* | `timeoutMs` | `TTCTL_TRANSPORT_TIMEOUT_MS` | 30000 | ≥ 1 |
|
|
49
|
+
* | `connectMs` | `TTCTL_TRANSPORT_CONNECT_TIMEOUT_MS` | 10000 | ≥ 1 |
|
|
50
|
+
* | `maxRetries` | `TTCTL_TRANSPORT_MAX_RETRIES` | 3 | 0–10 |
|
|
51
|
+
*
|
|
52
|
+
* Invalid values (NaN, negative, out-of-range) silently fall back to the
|
|
53
|
+
* default — the transport must not blow up on a stray operator typo in an
|
|
54
|
+
* MCP client env block.
|
|
55
|
+
*/
|
|
56
|
+
export interface TransportConfig {
|
|
57
|
+
/** Total request timeout in milliseconds applied to each attempt. */
|
|
58
|
+
timeoutMs: number;
|
|
59
|
+
/** Connection-establishment timeout in milliseconds. */
|
|
60
|
+
connectMs: number;
|
|
61
|
+
/** Maximum number of retry attempts for 429 and 5xx responses. */
|
|
62
|
+
maxRetries: number;
|
|
63
|
+
}
|
|
64
|
+
export declare function readTransportConfig(): TransportConfig;
|
|
65
|
+
/**
|
|
66
|
+
* Reset the cached transport config so the next {@link readTransportConfig}
|
|
67
|
+
* call re-reads the environment. Test-only — production callers never reach
|
|
68
|
+
* for this directly.
|
|
69
|
+
*/
|
|
70
|
+
export declare function resetTransportConfigCache(): void;
|
|
71
|
+
/**
|
|
72
|
+
* Parse an HTTP `Retry-After` header value into a delay in milliseconds.
|
|
73
|
+
*
|
|
74
|
+
* The header takes one of two forms (RFC 9110 § 10.2.3):
|
|
75
|
+
*
|
|
76
|
+
* - **delta-seconds** — an integer number of seconds (e.g. `Retry-After: 30`).
|
|
77
|
+
* - **HTTP-date** — an absolute timestamp (e.g.
|
|
78
|
+
* `Retry-After: Fri, 31 Dec 2025 23:59:59 GMT`); delay is computed as
|
|
79
|
+
* `target - now`, clamped to ≥ 0.
|
|
80
|
+
*
|
|
81
|
+
* Returns `undefined` when the header is absent, malformed, or yields a
|
|
82
|
+
* negative delay; callers fall back to computed exponential backoff.
|
|
83
|
+
*
|
|
84
|
+
* `nowMs` is injectable for deterministic tests.
|
|
85
|
+
*/
|
|
86
|
+
export declare function parseRetryAfter(headerValue: string | undefined, nowMs?: number): number | undefined;
|
|
87
|
+
/**
|
|
88
|
+
* Compute exponential-backoff delay in milliseconds for a retry attempt.
|
|
89
|
+
*
|
|
90
|
+
* Formula: `baseMs × 2^attempt`, with ±25 % uniform jitter, clamped to
|
|
91
|
+
* `capMs`. `attempt` is zero-indexed (0 = first retry).
|
|
92
|
+
*
|
|
93
|
+
* 429 responses use a longer base (250 ms) than 5xx (100 ms) so a rate-limit
|
|
94
|
+
* recovery walks back further than a transient server hiccup. The jitter
|
|
95
|
+
* (`random` injectable for tests) reduces the thundering-herd risk when many
|
|
96
|
+
* MCP tool calls land on the same 429 window simultaneously.
|
|
97
|
+
*/
|
|
98
|
+
export declare function computeBackoffDelay(reason: "rate-limit" | "server-error", attempt: number, random?: () => number): number;
|
|
99
|
+
/**
|
|
100
|
+
* Sleep for `ms` milliseconds, rejecting with the signal's abort reason if
|
|
101
|
+
* the caller aborts during the wait. Used for between-retry backoff so a
|
|
102
|
+
* cancellation propagates promptly rather than waiting out the full delay.
|
|
103
|
+
*/
|
|
104
|
+
export declare function sleepUnlessAborted(ms: number, signal?: AbortSignal): Promise<void>;
|
|
105
|
+
/**
|
|
106
|
+
* Combine the caller's `AbortSignal` (if any) with a per-attempt internal
|
|
107
|
+
* timeout into a single signal usable by the underlying transport. Returns
|
|
108
|
+
* the combined signal plus a `dispose()` to release the timeout resource
|
|
109
|
+
* once the attempt completes (preventing dangling timers).
|
|
110
|
+
*
|
|
111
|
+
* When no caller signal is provided, the combined signal IS the timeout
|
|
112
|
+
* signal directly — no `AbortSignal.any` wrapping overhead.
|
|
113
|
+
*/
|
|
114
|
+
export declare function combineSignals(callerSignal: AbortSignal | undefined, timeoutMs: number): {
|
|
115
|
+
signal: AbortSignal;
|
|
116
|
+
dispose: () => void;
|
|
117
|
+
};
|
|
118
|
+
/**
|
|
119
|
+
* Classify an error thrown by the underlying transport into a stable
|
|
120
|
+
* category so the retry loop can decide whether to retry, surface, or
|
|
121
|
+
* re-throw.
|
|
122
|
+
*
|
|
123
|
+
* - `aborted-by-caller` — the caller's signal aborted (cancellation).
|
|
124
|
+
* - `timeout` — the internal per-attempt timeout fired.
|
|
125
|
+
* - `network` — any other transport-level failure (DNS, socket
|
|
126
|
+
* reset, TLS error). NOT retried in v1 (could be a
|
|
127
|
+
* follow-up for #229 if empirical wedge data shows
|
|
128
|
+
* retries help).
|
|
129
|
+
*/
|
|
130
|
+
export declare function classifyTransportError(err: unknown, callerSignal: AbortSignal | undefined): "aborted-by-caller" | "timeout" | "network";
|
|
131
|
+
/**
|
|
132
|
+
* Determine whether a response status code is retryable per the issue
|
|
133
|
+
* #229 policy.
|
|
134
|
+
*/
|
|
135
|
+
export declare function isRetryableStatus(status: number): boolean;
|
|
136
|
+
//# sourceMappingURL=transport-resilience.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transport-resilience.d.ts","sourceRoot":"","sources":["../src/transport-resilience.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,qBAAa,cAAe,SAAQ,UAAU;aAO1B,OAAO,EAAE,aAAa;aACtB,QAAQ,EAAE,MAAM;aAChB,QAAQ,EAAE,MAAM;aAEhB,UAAU,CAAC,EAAE,MAAM;aACnB,gBAAgB,CAAC,EAAE,MAAM;IAX3C,SAAkB,IAAI,oBAAoB;IAC1C,QAAQ,CAAC,IAAI,EAAE,SAAS,GAAG,SAAS,GAAG,cAAc,GAAG,cAAc,CAAC;IACvE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;gBAGxB,IAAI,EAAE,SAAS,GAAG,SAAS,GAAG,cAAc,GAAG,cAAc,EAC7C,OAAO,EAAE,aAAa,EACtB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChC,OAAO,EAAE,MAAM,EACC,UAAU,CAAC,EAAE,MAAM,YAAA,EACnB,gBAAgB,CAAC,EAAE,MAAM,YAAA,EACzC,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE;CAMhC;AAUD;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,WAAW,eAAe;IAC9B,qEAAqE;IACrE,SAAS,EAAE,MAAM,CAAC;IAClB,wDAAwD;IACxD,SAAS,EAAE,MAAM,CAAC;IAClB,kEAAkE;IAClE,UAAU,EAAE,MAAM,CAAC;CACpB;AAUD,wBAAgB,mBAAmB,IAAI,eAAe,CAQrD;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,IAAI,IAAI,CAEhD;AAkBD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,EAAE,KAAK,GAAE,MAAmB,GAAG,MAAM,GAAG,SAAS,CAmB/G;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,YAAY,GAAG,cAAc,EACrC,OAAO,EAAE,MAAM,EACf,MAAM,GAAE,MAAM,MAAoB,GACjC,MAAM,CAMR;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAsBlF;AAeD;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAC5B,YAAY,EAAE,WAAW,GAAG,SAAS,EACrC,SAAS,EAAE,MAAM,GAChB;IAAE,MAAM,EAAE,WAAW,CAAC;IAAC,OAAO,EAAE,MAAM,IAAI,CAAA;CAAE,CAe9C;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,sBAAsB,CACpC,GAAG,EAAE,OAAO,EACZ,YAAY,EAAE,WAAW,GAAG,SAAS,GACpC,mBAAmB,GAAG,SAAS,GAAG,SAAS,CAO7C;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAEzD"}
|
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-only
|
|
2
|
+
// Copyright (C) 2026 Oleksii PELYKH
|
|
3
|
+
import { TtctlError } from "./auth/errors.js";
|
|
4
|
+
/**
|
|
5
|
+
* Final-failure transport error raised after all retries are exhausted or
|
|
6
|
+
* when a fatal signal-driven condition (caller abort, internal timeout)
|
|
7
|
+
* terminates the request loop.
|
|
8
|
+
*
|
|
9
|
+
* Extends {@link TtctlError} so it propagates through service callers'
|
|
10
|
+
* `if (err instanceof TtctlError) throw err;` guard verbatim — surfaces
|
|
11
|
+
* (CLI / MCP) render `error.recovery` directly.
|
|
12
|
+
*
|
|
13
|
+
* **Codes**:
|
|
14
|
+
*
|
|
15
|
+
* - `TIMEOUT` — internal per-request timeout fired (default 30s,
|
|
16
|
+
* overridable via `TTCTL_TRANSPORT_TIMEOUT_MS`). The
|
|
17
|
+
* underlying socket/handshake never completed in time.
|
|
18
|
+
* - `ABORTED` — caller's `AbortSignal` aborted before the request
|
|
19
|
+
* completed. Typically driven by the MCP client cancelling
|
|
20
|
+
* an in-flight tool call.
|
|
21
|
+
* - `RATE_LIMITED` — HTTP 429 returned by the surface and the retry budget
|
|
22
|
+
* was exhausted. `lastRetryAfterMs` (when set) reports
|
|
23
|
+
* the server's last `Retry-After` hint.
|
|
24
|
+
* - `SERVER_ERROR` — HTTP 5xx returned by the surface and the retry budget
|
|
25
|
+
* was exhausted.
|
|
26
|
+
*/
|
|
27
|
+
export class TransportError extends TtctlError {
|
|
28
|
+
surface;
|
|
29
|
+
endpoint;
|
|
30
|
+
attempts;
|
|
31
|
+
lastStatus;
|
|
32
|
+
lastRetryAfterMs;
|
|
33
|
+
name = "TransportError";
|
|
34
|
+
code;
|
|
35
|
+
recovery;
|
|
36
|
+
constructor(code, surface, endpoint, attempts, message, lastStatus, lastRetryAfterMs, options) {
|
|
37
|
+
super(message, options);
|
|
38
|
+
this.surface = surface;
|
|
39
|
+
this.endpoint = endpoint;
|
|
40
|
+
this.attempts = attempts;
|
|
41
|
+
this.lastStatus = lastStatus;
|
|
42
|
+
this.lastRetryAfterMs = lastRetryAfterMs;
|
|
43
|
+
this.code = code;
|
|
44
|
+
this.recovery = RECOVERY[code];
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
const RECOVERY = {
|
|
48
|
+
TIMEOUT: "The Toptal API did not respond in time. Try again; if the wedge persists, file an issue.",
|
|
49
|
+
ABORTED: "Request was cancelled by the caller before it completed.",
|
|
50
|
+
RATE_LIMITED: "Toptal returned HTTP 429 (rate limited) after the configured retry budget. Wait a few minutes and retry.",
|
|
51
|
+
SERVER_ERROR: "Toptal returned a 5xx response after the configured retry budget. Retry later or file an issue.",
|
|
52
|
+
};
|
|
53
|
+
const DEFAULT_CONFIG = Object.freeze({
|
|
54
|
+
timeoutMs: 30_000,
|
|
55
|
+
connectMs: 10_000,
|
|
56
|
+
maxRetries: 3,
|
|
57
|
+
});
|
|
58
|
+
let cachedConfig;
|
|
59
|
+
export function readTransportConfig() {
|
|
60
|
+
if (cachedConfig !== undefined)
|
|
61
|
+
return cachedConfig;
|
|
62
|
+
cachedConfig = {
|
|
63
|
+
timeoutMs: readPositiveIntEnv("TTCTL_TRANSPORT_TIMEOUT_MS", DEFAULT_CONFIG.timeoutMs),
|
|
64
|
+
connectMs: readPositiveIntEnv("TTCTL_TRANSPORT_CONNECT_TIMEOUT_MS", DEFAULT_CONFIG.connectMs),
|
|
65
|
+
maxRetries: readBoundedIntEnv("TTCTL_TRANSPORT_MAX_RETRIES", DEFAULT_CONFIG.maxRetries, 0, 10),
|
|
66
|
+
};
|
|
67
|
+
return cachedConfig;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Reset the cached transport config so the next {@link readTransportConfig}
|
|
71
|
+
* call re-reads the environment. Test-only — production callers never reach
|
|
72
|
+
* for this directly.
|
|
73
|
+
*/
|
|
74
|
+
export function resetTransportConfigCache() {
|
|
75
|
+
cachedConfig = undefined;
|
|
76
|
+
}
|
|
77
|
+
function readPositiveIntEnv(name, defaultValue) {
|
|
78
|
+
const raw = process.env[name];
|
|
79
|
+
if (raw === undefined || raw === "")
|
|
80
|
+
return defaultValue;
|
|
81
|
+
const parsed = Number.parseInt(raw, 10);
|
|
82
|
+
if (!Number.isFinite(parsed) || parsed < 1)
|
|
83
|
+
return defaultValue;
|
|
84
|
+
return parsed;
|
|
85
|
+
}
|
|
86
|
+
function readBoundedIntEnv(name, defaultValue, min, max) {
|
|
87
|
+
const raw = process.env[name];
|
|
88
|
+
if (raw === undefined || raw === "")
|
|
89
|
+
return defaultValue;
|
|
90
|
+
const parsed = Number.parseInt(raw, 10);
|
|
91
|
+
if (!Number.isFinite(parsed) || parsed < min || parsed > max)
|
|
92
|
+
return defaultValue;
|
|
93
|
+
return parsed;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Parse an HTTP `Retry-After` header value into a delay in milliseconds.
|
|
97
|
+
*
|
|
98
|
+
* The header takes one of two forms (RFC 9110 § 10.2.3):
|
|
99
|
+
*
|
|
100
|
+
* - **delta-seconds** — an integer number of seconds (e.g. `Retry-After: 30`).
|
|
101
|
+
* - **HTTP-date** — an absolute timestamp (e.g.
|
|
102
|
+
* `Retry-After: Fri, 31 Dec 2025 23:59:59 GMT`); delay is computed as
|
|
103
|
+
* `target - now`, clamped to ≥ 0.
|
|
104
|
+
*
|
|
105
|
+
* Returns `undefined` when the header is absent, malformed, or yields a
|
|
106
|
+
* negative delay; callers fall back to computed exponential backoff.
|
|
107
|
+
*
|
|
108
|
+
* `nowMs` is injectable for deterministic tests.
|
|
109
|
+
*/
|
|
110
|
+
export function parseRetryAfter(headerValue, nowMs = Date.now()) {
|
|
111
|
+
if (headerValue === undefined)
|
|
112
|
+
return undefined;
|
|
113
|
+
const trimmed = headerValue.trim();
|
|
114
|
+
if (trimmed === "")
|
|
115
|
+
return undefined;
|
|
116
|
+
// delta-seconds — integer form first; tolerant of leading-zero / surrounding-space variants.
|
|
117
|
+
if (/^\d+$/.test(trimmed)) {
|
|
118
|
+
const seconds = Number.parseInt(trimmed, 10);
|
|
119
|
+
if (!Number.isFinite(seconds) || seconds < 0)
|
|
120
|
+
return undefined;
|
|
121
|
+
return seconds * 1000;
|
|
122
|
+
}
|
|
123
|
+
// HTTP-date form. RFC 9110 requires `IMF-fixdate` / `obs-date` shapes
|
|
124
|
+
// which always carry alphabetic day-name / month-name tokens; reject
|
|
125
|
+
// pure-numeric leftovers (e.g. `"-1"`, `"12.5"`) that `Date.parse`
|
|
126
|
+
// would otherwise opportunistically interpret as a year.
|
|
127
|
+
if (!/[A-Za-z]/.test(trimmed))
|
|
128
|
+
return undefined;
|
|
129
|
+
const parsed = Date.parse(trimmed);
|
|
130
|
+
if (Number.isNaN(parsed))
|
|
131
|
+
return undefined;
|
|
132
|
+
const delta = parsed - nowMs;
|
|
133
|
+
return delta > 0 ? delta : 0;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Compute exponential-backoff delay in milliseconds for a retry attempt.
|
|
137
|
+
*
|
|
138
|
+
* Formula: `baseMs × 2^attempt`, with ±25 % uniform jitter, clamped to
|
|
139
|
+
* `capMs`. `attempt` is zero-indexed (0 = first retry).
|
|
140
|
+
*
|
|
141
|
+
* 429 responses use a longer base (250 ms) than 5xx (100 ms) so a rate-limit
|
|
142
|
+
* recovery walks back further than a transient server hiccup. The jitter
|
|
143
|
+
* (`random` injectable for tests) reduces the thundering-herd risk when many
|
|
144
|
+
* MCP tool calls land on the same 429 window simultaneously.
|
|
145
|
+
*/
|
|
146
|
+
export function computeBackoffDelay(reason, attempt, random = Math.random) {
|
|
147
|
+
const baseMs = reason === "rate-limit" ? 250 : 100;
|
|
148
|
+
const capMs = 30_000;
|
|
149
|
+
const raw = baseMs * 2 ** attempt;
|
|
150
|
+
const jitter = 1 + (random() * 2 - 1) * 0.25; // ±25%
|
|
151
|
+
return Math.min(Math.max(0, Math.round(raw * jitter)), capMs);
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Sleep for `ms` milliseconds, rejecting with the signal's abort reason if
|
|
155
|
+
* the caller aborts during the wait. Used for between-retry backoff so a
|
|
156
|
+
* cancellation propagates promptly rather than waiting out the full delay.
|
|
157
|
+
*/
|
|
158
|
+
export function sleepUnlessAborted(ms, signal) {
|
|
159
|
+
return new Promise((resolve, reject) => {
|
|
160
|
+
if (signal?.aborted) {
|
|
161
|
+
reject(toError(signal.reason));
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
const timer = setTimeout(() => {
|
|
165
|
+
if (signal !== undefined) {
|
|
166
|
+
signal.removeEventListener("abort", onAbort);
|
|
167
|
+
}
|
|
168
|
+
resolve();
|
|
169
|
+
}, ms);
|
|
170
|
+
const onAbort = () => {
|
|
171
|
+
clearTimeout(timer);
|
|
172
|
+
// `signal` is guaranteed defined here — `onAbort` is registered only
|
|
173
|
+
// via the `signal?.addEventListener` branch below — but the listener
|
|
174
|
+
// closure references the outer-scope binding so eslint cannot infer
|
|
175
|
+
// narrowing across the boundary. Read defensively.
|
|
176
|
+
reject(toError(signal?.reason));
|
|
177
|
+
};
|
|
178
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Normalise an arbitrary `AbortSignal.reason` value into an `Error`. The
|
|
183
|
+
* runtime convention is for `reason` to BE an `Error` (DOMException for
|
|
184
|
+
* `AbortSignal.timeout`, custom `Error` for `AbortController.abort(err)`),
|
|
185
|
+
* but the type is `unknown` and operators occasionally pass strings or
|
|
186
|
+
* `undefined`. Wrap non-Error shapes so downstream Promise consumers
|
|
187
|
+
* always see a real Error.
|
|
188
|
+
*/
|
|
189
|
+
function toError(value) {
|
|
190
|
+
if (value instanceof Error)
|
|
191
|
+
return value;
|
|
192
|
+
return new Error(typeof value === "string" ? value : "Aborted");
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Combine the caller's `AbortSignal` (if any) with a per-attempt internal
|
|
196
|
+
* timeout into a single signal usable by the underlying transport. Returns
|
|
197
|
+
* the combined signal plus a `dispose()` to release the timeout resource
|
|
198
|
+
* once the attempt completes (preventing dangling timers).
|
|
199
|
+
*
|
|
200
|
+
* When no caller signal is provided, the combined signal IS the timeout
|
|
201
|
+
* signal directly — no `AbortSignal.any` wrapping overhead.
|
|
202
|
+
*/
|
|
203
|
+
export function combineSignals(callerSignal, timeoutMs) {
|
|
204
|
+
const timeoutController = new AbortController();
|
|
205
|
+
const timer = setTimeout(() => {
|
|
206
|
+
timeoutController.abort(new DOMException("Transport request timed out.", "TimeoutError"));
|
|
207
|
+
}, timeoutMs);
|
|
208
|
+
// Unref so a stray timer doesn't keep Node alive on early caller resolution.
|
|
209
|
+
timer.unref();
|
|
210
|
+
const signal = callerSignal === undefined ? timeoutController.signal : AbortSignal.any([callerSignal, timeoutController.signal]);
|
|
211
|
+
return {
|
|
212
|
+
signal,
|
|
213
|
+
dispose: () => {
|
|
214
|
+
clearTimeout(timer);
|
|
215
|
+
},
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Classify an error thrown by the underlying transport into a stable
|
|
220
|
+
* category so the retry loop can decide whether to retry, surface, or
|
|
221
|
+
* re-throw.
|
|
222
|
+
*
|
|
223
|
+
* - `aborted-by-caller` — the caller's signal aborted (cancellation).
|
|
224
|
+
* - `timeout` — the internal per-attempt timeout fired.
|
|
225
|
+
* - `network` — any other transport-level failure (DNS, socket
|
|
226
|
+
* reset, TLS error). NOT retried in v1 (could be a
|
|
227
|
+
* follow-up for #229 if empirical wedge data shows
|
|
228
|
+
* retries help).
|
|
229
|
+
*/
|
|
230
|
+
export function classifyTransportError(err, callerSignal) {
|
|
231
|
+
if (callerSignal?.aborted)
|
|
232
|
+
return "aborted-by-caller";
|
|
233
|
+
if (err instanceof DOMException && err.name === "TimeoutError")
|
|
234
|
+
return "timeout";
|
|
235
|
+
if (err instanceof Error && (err.name === "AbortError" || err.name === "TimeoutError")) {
|
|
236
|
+
return "timeout";
|
|
237
|
+
}
|
|
238
|
+
return "network";
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Determine whether a response status code is retryable per the issue
|
|
242
|
+
* #229 policy.
|
|
243
|
+
*/
|
|
244
|
+
export function isRetryableStatus(status) {
|
|
245
|
+
return status === 429 || (status >= 500 && status < 600);
|
|
246
|
+
}
|
|
247
|
+
//# sourceMappingURL=transport-resilience.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transport-resilience.js","sourceRoot":"","sources":["../src/transport-resilience.ts"],"names":[],"mappings":"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"}
|