@apifuse/provider-sdk 2.2.0-beta.5 → 2.2.0-beta.8
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/AUTHORING.md +53 -0
- package/CHANGELOG.md +12 -0
- package/README.md +5 -1
- package/SUBMISSION.md +1 -1
- package/bin/apifuse-check.ts +26 -1
- package/bin/apifuse-pack-check.ts +14 -0
- package/bin/apifuse-submit-check.ts +193 -2
- package/bin/apifuse-sync-assets.ts +117 -0
- package/dist/auth-turn/index.d.ts +2 -2
- package/dist/cli/commands.d.ts +1 -1
- package/dist/cli/commands.js +8 -0
- package/dist/cli/create.d.ts +3 -0
- package/dist/cli/create.js +34 -35
- package/dist/cli/prompt-assets.d.ts +80 -0
- package/dist/cli/prompt-assets.js +743 -0
- package/dist/cli/templates/provider/AGENTS.md.tpl +17 -8
- package/dist/config/loader.d.ts +79 -6
- package/dist/config/loader.js +272 -48
- package/dist/define.js +27 -3
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/runtime/executor.js +7 -0
- package/dist/runtime/http.js +3 -0
- package/dist/runtime/proxy-errors.js +6 -2
- package/dist/runtime/proxy-nodemaven.d.ts +34 -0
- package/dist/runtime/proxy-nodemaven.js +128 -0
- package/dist/runtime/proxy-telemetry.d.ts +2 -1
- package/dist/runtime/proxy-telemetry.js +39 -4
- package/dist/runtime/secrets.d.ts +27 -0
- package/dist/runtime/secrets.js +51 -0
- package/dist/runtime/stealth.js +20 -9
- package/dist/server/serve.d.ts +5 -0
- package/dist/server/serve.js +39 -0
- package/dist/server/types.d.ts +9 -9
- package/dist/types.d.ts +30 -1
- package/package.json +4 -3
- package/src/cli/commands.ts +10 -0
- package/src/cli/create.ts +42 -35
- package/src/cli/prompt-assets.ts +865 -0
- package/src/cli/templates/provider/AGENTS.md.tpl +17 -8
- package/src/config/loader.ts +405 -61
- package/src/define.ts +35 -3
- package/src/index.ts +5 -0
- package/src/runtime/executor.ts +8 -0
- package/src/runtime/http.ts +3 -0
- package/src/runtime/proxy-errors.ts +12 -4
- package/src/runtime/proxy-nodemaven.ts +178 -0
- package/src/runtime/proxy-telemetry.ts +56 -5
- package/src/runtime/secrets.ts +64 -0
- package/src/runtime/stealth.ts +26 -10
- package/src/server/serve.ts +53 -0
- package/src/types.ts +30 -1
- package/dist/cli/templates/provider/CLAUDE.md.tpl +0 -1
- package/src/cli/templates/provider/CLAUDE.md.tpl +0 -1
- /package/dist/cli/templates/provider/{skills → .agents/skills}/fixtures-and-recording/SKILL.md.tpl +0 -0
- /package/dist/cli/templates/provider/{skills → .agents/skills}/health-checks-and-fail-closed/SKILL.md.tpl +0 -0
- /package/dist/cli/templates/provider/{skills → .agents/skills}/normalization-standards/SKILL.md.tpl +0 -0
- /package/dist/cli/templates/provider/{skills → .agents/skills}/pagination-and-counts/SKILL.md.tpl +0 -0
- /package/dist/cli/templates/provider/{skills → .agents/skills}/upstream-contract-verification/SKILL.md.tpl +0 -0
- /package/dist/cli/templates/provider/{skills → .agents/skills}/upstream-notes/README.md.tpl +0 -0
- /package/src/cli/templates/provider/{skills → .agents/skills}/fixtures-and-recording/SKILL.md.tpl +0 -0
- /package/src/cli/templates/provider/{skills → .agents/skills}/health-checks-and-fail-closed/SKILL.md.tpl +0 -0
- /package/src/cli/templates/provider/{skills → .agents/skills}/normalization-standards/SKILL.md.tpl +0 -0
- /package/src/cli/templates/provider/{skills → .agents/skills}/pagination-and-counts/SKILL.md.tpl +0 -0
- /package/src/cli/templates/provider/{skills → .agents/skills}/upstream-contract-verification/SKILL.md.tpl +0 -0
- /package/src/cli/templates/provider/{skills → .agents/skills}/upstream-notes/README.md.tpl +0 -0
|
@@ -4,8 +4,8 @@ You are building an APIFuse provider. APIFuse turns messy upstream APIs into
|
|
|
4
4
|
normalized, typed, evidence-backed public APIs. A provider that merely proxies
|
|
5
5
|
the upstream is a failed provider, even if every check passes.
|
|
6
6
|
|
|
7
|
-
This file is the core contract. Detailed procedures live in
|
|
8
|
-
the matching skill BEFORE working on that area (index at the bottom).
|
|
7
|
+
This file is the core contract. Detailed procedures live in `.agents/skills/` —
|
|
8
|
+
load the matching skill BEFORE working on that area (index at the bottom).
|
|
9
9
|
|
|
10
10
|
## Non-negotiable principles
|
|
11
11
|
|
|
@@ -75,13 +75,22 @@ bun run submit-check # structural score; a high score does NOT prove quality
|
|
|
75
75
|
`submit-check` is a structural gate. Every principle above can be violated
|
|
76
76
|
while scoring 95/100 — reviewers and CI audit for exactly these classes.
|
|
77
77
|
|
|
78
|
+
## Managed prompt assets
|
|
79
|
+
|
|
80
|
+
`AGENTS.md` and `.agents/skills/**` are generated by the SDK; `CLAUDE.md`,
|
|
81
|
+
`.claude`, and `.codex` are symlinks onto them so every agent CLI reads the
|
|
82
|
+
same contract. Do not hand-edit these files — regenerate them with
|
|
83
|
+
`bun run sync-assets` (or `bunx apifuse sync-assets .`). `apifuse check` and
|
|
84
|
+
`submit-check` enforce a freshness gate: stale or modified prompt assets
|
|
85
|
+
(tracked in `.apifuse/prompt-assets.json`) block submission until re-synced.
|
|
86
|
+
|
|
78
87
|
## Skill index — load before working on:
|
|
79
88
|
|
|
80
89
|
| Area | Load |
|
|
81
90
|
| --- | --- |
|
|
82
|
-
| Output schemas, mappers, field naming, timestamps, enums |
|
|
83
|
-
| Upstream request params, new endpoint wiring, field mapping |
|
|
84
|
-
| Recording fixtures, writing tests against fixtures |
|
|
85
|
-
| List operations, paging, totals, client-side filtering |
|
|
86
|
-
| healthCheck blocks, error classification, fail-closed guards |
|
|
87
|
-
| Upstream-specific known pitfalls for THIS bounty |
|
|
91
|
+
| Output schemas, mappers, field naming, timestamps, enums | `.agents/skills/normalization-standards/SKILL.md` |
|
|
92
|
+
| Upstream request params, new endpoint wiring, field mapping | `.agents/skills/upstream-contract-verification/SKILL.md` |
|
|
93
|
+
| Recording fixtures, writing tests against fixtures | `.agents/skills/fixtures-and-recording/SKILL.md` |
|
|
94
|
+
| List operations, paging, totals, client-side filtering | `.agents/skills/pagination-and-counts/SKILL.md` |
|
|
95
|
+
| healthCheck blocks, error classification, fail-closed guards | `.agents/skills/health-checks-and-fail-closed/SKILL.md` |
|
|
96
|
+
| Upstream-specific known pitfalls for THIS bounty | `.agents/skills/upstream-notes/` (read every file) |
|
package/dist/config/loader.d.ts
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import { Redis } from "ioredis";
|
|
2
2
|
import type { ProviderProxyPolicy, TraceConfig } from "../types.js";
|
|
3
|
+
import { type ProxyProtocol } from "../runtime/proxy-nodemaven.js";
|
|
4
|
+
export type { ProxyProtocol } from "../runtime/proxy-nodemaven.js";
|
|
5
|
+
/** Proxy vendors the SDK resolves natively (as opposed to the static env path). */
|
|
6
|
+
export type ProxyVendorName = "smartproxy" | "nodemaven";
|
|
3
7
|
export declare const SMARTPROXY_APP_KEY_ENV = "APIFUSE__PROXY__SMARTPROXY_APP_KEY";
|
|
4
8
|
export declare const SMARTPROXY_MAX_LIFETIME_MINUTES = 2000;
|
|
5
9
|
export declare const DEFAULT_SMARTPROXY_POOL_SIZE = 20;
|
|
@@ -42,12 +46,33 @@ export type ProxyResolutionOptions = {
|
|
|
42
46
|
affinityKey?: string;
|
|
43
47
|
/** Zero-based proxy-pool attempt index used by SDK transports for failover. */
|
|
44
48
|
proxyAttempt?: number;
|
|
49
|
+
/**
|
|
50
|
+
* Tunnelling protocols the calling transport can use. When a resolved
|
|
51
|
+
* protocol is not in this set the resolver fails with
|
|
52
|
+
* `PROXY_PROTOCOL_UNSUPPORTED` instead of silently downgrading. Unset means
|
|
53
|
+
* permissive (both protocols allowed).
|
|
54
|
+
*/
|
|
55
|
+
transportProtocols?: readonly ProxyProtocol[];
|
|
56
|
+
/**
|
|
57
|
+
* Explicit protocol override. Internal — for the verification harness and
|
|
58
|
+
* tests, or an advanced caller. Normal callers omit it and each vendor uses
|
|
59
|
+
* its own benchmarked default protocol (see VENDOR_DEFAULT_PROTOCOL). Not an
|
|
60
|
+
* env var and not a provider-policy field.
|
|
61
|
+
*/
|
|
62
|
+
protocol?: ProxyProtocol;
|
|
63
|
+
/**
|
|
64
|
+
* Gateway pool "refresh" generation. Bumped by transports on pool refresh to
|
|
65
|
+
* derive a fresh gateway session set (ignored by allocation-style vendors,
|
|
66
|
+
* whose refresh is driven by cache invalidation).
|
|
67
|
+
*/
|
|
68
|
+
proxyRefreshEpoch?: number;
|
|
45
69
|
telemetry?: ProxyTelemetrySink;
|
|
46
70
|
};
|
|
47
71
|
export type ProxyCacheStatus = "memory_hit" | "redis_hit" | "allocator" | "soft_stale_refresh" | "lock_wait" | "redis_error" | "redis_corrupt" | "disabled";
|
|
48
72
|
export type SmartproxyAllocatorBodyClass = "network_error" | "http_error" | "empty" | "json_without_proxies" | "text_without_proxies" | "usable_proxy_endpoints";
|
|
49
73
|
export type ProxyResolutionTelemetryEvent = {
|
|
50
|
-
provider:
|
|
74
|
+
provider: ProxyVendorName;
|
|
75
|
+
protocol?: ProxyProtocol;
|
|
51
76
|
cacheStatus: ProxyCacheStatus;
|
|
52
77
|
cacheHit: boolean;
|
|
53
78
|
resolutionMs: number;
|
|
@@ -64,7 +89,7 @@ export type ProxyResolutionTelemetryEvent = {
|
|
|
64
89
|
refreshes?: number;
|
|
65
90
|
};
|
|
66
91
|
export type ProxyAttemptTelemetryEvent = {
|
|
67
|
-
provider:
|
|
92
|
+
provider: ProxyVendorName;
|
|
68
93
|
attempt: number;
|
|
69
94
|
poolIndex?: number;
|
|
70
95
|
proxyHash?: string;
|
|
@@ -73,22 +98,40 @@ export type ProxyAttemptTelemetryEvent = {
|
|
|
73
98
|
status?: number;
|
|
74
99
|
durationMs?: number;
|
|
75
100
|
};
|
|
101
|
+
export type ProxyVendorFailoverTelemetryEvent = {
|
|
102
|
+
/** Vendor that failed or was skipped. */
|
|
103
|
+
vendor: ProxyVendorName;
|
|
104
|
+
/** Vendor tried next, or undefined when the chain is exhausted. */
|
|
105
|
+
nextVendor?: ProxyVendorName;
|
|
106
|
+
phase: "resolution" | "transport";
|
|
107
|
+
reason: "no_credentials" | "allocation_failed" | "pool_exhausted" | "protocol_unsupported";
|
|
108
|
+
attempt?: number;
|
|
109
|
+
};
|
|
76
110
|
export type ProxyTelemetrySink = {
|
|
77
111
|
recordProxyResolution(event: ProxyResolutionTelemetryEvent): void;
|
|
78
112
|
recordProxyAttempt?(event: ProxyAttemptTelemetryEvent): void;
|
|
113
|
+
recordProxyVendorFailover?(event: ProxyVendorFailoverTelemetryEvent): void;
|
|
79
114
|
};
|
|
80
115
|
export type ResolvedProxyConfig = {
|
|
81
116
|
shouldWarn: boolean;
|
|
82
117
|
url?: string;
|
|
83
|
-
source?: "explicit" | "env" | "config" | "smartproxy-allocator";
|
|
118
|
+
source?: "explicit" | "env" | "config" | "smartproxy-allocator" | "nodemaven-gateway";
|
|
119
|
+
protocol?: ProxyProtocol;
|
|
84
120
|
diagnostics?: Record<string, string | number | boolean>;
|
|
85
121
|
};
|
|
122
|
+
export type ProxyResolutionErrorCode = "PROXY_REQUIRED" | "PROXY_ALLOCATION_FAILED" | "PROXY_PROTOCOL_UNSUPPORTED";
|
|
86
123
|
export declare class ProxyResolutionError extends Error {
|
|
87
|
-
readonly code:
|
|
124
|
+
readonly code: ProxyResolutionErrorCode;
|
|
88
125
|
readonly telemetry?: ProxyResolutionTelemetryEvent;
|
|
89
|
-
|
|
126
|
+
readonly vendor?: ProxyVendorName;
|
|
127
|
+
readonly vendorChain?: ProxyVendorName[];
|
|
128
|
+
readonly protocol?: ProxyProtocol;
|
|
129
|
+
constructor(code: ProxyResolutionErrorCode, message: string, options?: {
|
|
90
130
|
cause?: unknown;
|
|
91
131
|
telemetry?: ProxyResolutionTelemetryEvent;
|
|
132
|
+
vendor?: ProxyVendorName;
|
|
133
|
+
vendorChain?: ProxyVendorName[];
|
|
134
|
+
protocol?: ProxyProtocol;
|
|
92
135
|
});
|
|
93
136
|
}
|
|
94
137
|
type ProxyRedisClient = Pick<Redis, "connect" | "del" | "eval" | "get" | "on" | "pttl" | "set" | "status">;
|
|
@@ -99,9 +142,39 @@ export declare function __setProxyRedisForTests(redis: ProxyRedisClient | undefi
|
|
|
99
142
|
export declare function __setSmartproxyAllocatorDeadlineMsForTests(deadlineMs: number | undefined): void;
|
|
100
143
|
export declare function resolveProxyConfig(options?: ProxyResolutionOptions): ResolvedProxyConfig;
|
|
101
144
|
export declare function resolveProxyConfigAsync(options?: ProxyResolutionOptions): Promise<ResolvedProxyConfig>;
|
|
145
|
+
/**
|
|
146
|
+
* Guard the No-MITM invariant: a resolved proxy URL must use a tunnelling scheme
|
|
147
|
+
* (http CONNECT or socks5) so the client TLS handshake reaches the origin
|
|
148
|
+
* end-to-end. Anything else would intercept TLS and break fingerprinting.
|
|
149
|
+
*/
|
|
150
|
+
export declare function assertTunnelingScheme(url: string): void;
|
|
151
|
+
/**
|
|
152
|
+
* Ordered list of SDK-native proxy vendors declared by the policy. `providers`
|
|
153
|
+
* takes precedence over the legacy singular `provider`; the platform default
|
|
154
|
+
* env is the final fallback. Non-registry names (decodo/custom) are dropped so
|
|
155
|
+
* an all-static chain falls through to the legacy env-URL path unchanged.
|
|
156
|
+
*/
|
|
157
|
+
export declare function resolveVendorChain(policy: ProviderProxyPolicy): ProxyVendorName[];
|
|
158
|
+
/**
|
|
159
|
+
* Total attempt span across a policy's vendor chain — the sum of each vendor's
|
|
160
|
+
* pool size. Transports use this so successive attempts rotate a vendor's pool
|
|
161
|
+
* and then fail over to the next vendor via the flat attempt index. With one
|
|
162
|
+
* vendor this equals that vendor's pool size (today's behaviour).
|
|
163
|
+
*/
|
|
164
|
+
export declare function resolvePolicyProxyPoolSpan(policy: ProviderProxyPolicy): number;
|
|
165
|
+
/** Map a resolved proxy source label to the vendor that served it. */
|
|
166
|
+
export declare function vendorFromResolvedSource(source: ResolvedProxyConfig["source"]): ProxyVendorName | undefined;
|
|
167
|
+
/**
|
|
168
|
+
* Map a flat attempt index into (vendorIndex, poolIndex) by concatenating each
|
|
169
|
+
* vendor's pool space in chain order. With a single vendor this reduces to
|
|
170
|
+
* `attempt % poolSize`, preserving today's behaviour exactly.
|
|
171
|
+
*/
|
|
172
|
+
export declare function mapFlatAttempt(flat: number, sizes: readonly number[]): {
|
|
173
|
+
vendorIndex: number;
|
|
174
|
+
poolIndex: number;
|
|
175
|
+
};
|
|
102
176
|
export declare function clearProxyResolutionCache(): void;
|
|
103
177
|
export declare function invalidateProxyResolutionCache(options?: ProxyResolutionOptions): boolean;
|
|
104
178
|
export declare function invalidateProxyResolutionCacheAsync(options?: ProxyResolutionOptions): Promise<boolean>;
|
|
105
179
|
export declare function defineConfig(config: ApiFuseConfig): ApiFuseConfig;
|
|
106
180
|
export declare function loadApiFuseConfig(dir?: string): Promise<ApiFuseConfig>;
|
|
107
|
-
export {};
|