@apifuse/provider-sdk 2.1.0-beta.5 → 2.1.0-beta.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -0
- package/README.md +2 -2
- package/SUBMISSION.md +2 -1
- package/bin/apifuse-check.ts +60 -6
- package/bin/apifuse-dev.ts +48 -5
- package/bin/apifuse-perf.ts +50 -11
- package/bin/apifuse-record.ts +35 -11
- package/bin/apifuse-submit-check.ts +1425 -3
- package/package.json +107 -92
- package/src/ceremonies/index.ts +8 -2
- package/src/choice-token.ts +1 -0
- package/src/cli/commands.ts +8 -5
- package/src/cli/create.ts +28 -0
- package/src/cli/templates/provider/operations/ping.ts.tpl +3 -2
- package/src/cli/templates/provider/schemas/ping.ts.tpl +8 -0
- package/src/config/loader.ts +19 -1
- package/src/contract-json.ts +75 -0
- package/src/contract-serialization.ts +89 -0
- package/src/contract-types.ts +52 -0
- package/src/contract.ts +215 -0
- package/src/define.ts +37 -2
- package/src/errors.ts +15 -0
- package/src/i18n/catalog.ts +156 -0
- package/src/index.ts +22 -1
- package/src/lint.ts +256 -37
- package/src/provider.ts +45 -2
- package/src/runtime/browser.ts +685 -30
- package/src/runtime/cache.ts +35 -89
- package/src/runtime/choice.ts +760 -0
- package/src/runtime/executor.ts +19 -2
- package/src/runtime/redis.ts +116 -0
- package/src/runtime/state.ts +487 -0
- package/src/runtime/stealth.ts +8 -1
- package/src/server/serve.ts +361 -46
- package/src/server/types.ts +2 -0
- package/src/testing/run.ts +16 -3
- package/src/types.ts +209 -6
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# @apifuse/provider-sdk Changelog
|
|
2
2
|
|
|
3
|
+
## 2.1.0-beta.6
|
|
4
|
+
|
|
5
|
+
- Public repository clean-import release for `APIFuseHQ/provider-sdk`.
|
|
6
|
+
- Preserves the monorepo SDK exports required by ApiFuse provider registry cutover, including `./contract` and provider i18n helpers.
|
|
7
|
+
|
|
8
|
+
|
|
3
9
|
## 2.1.0-beta.5
|
|
4
10
|
|
|
5
11
|
- Republish the bounty workspace DX hardening that accepts generated readonly metadata and factored `defineOperation()` maps during standalone TypeScript checks.
|
package/README.md
CHANGED
|
@@ -216,11 +216,11 @@ Operations declare non-functional metadata via `annotations`:
|
|
|
216
216
|
apifuse create <name>
|
|
217
217
|
apifuse dev [path]
|
|
218
218
|
apifuse check [path]
|
|
219
|
-
apifuse record providers/
|
|
219
|
+
apifuse record providers/korea-air-quality --operation realtime --params '{"stationName":"종로구"}'
|
|
220
220
|
apifuse test [path]
|
|
221
221
|
apifuse submit-check [path] --tier bronze --markdown submission-report.md
|
|
222
222
|
apifuse bounty-check [path]
|
|
223
|
-
apifuse perf providers/
|
|
223
|
+
apifuse perf providers/korea-air-quality --operation realtime --params '{"stationName":"종로구"}'
|
|
224
224
|
```
|
|
225
225
|
|
|
226
226
|
`apifuse record` is for real upstream-backed operations that declare
|
package/SUBMISSION.md
CHANGED
|
@@ -48,8 +48,9 @@ Fix all blockers before submitting:
|
|
|
48
48
|
- Missing `healthCheck` or `healthCheckUnsupported` on any Operation.
|
|
49
49
|
- Credential-backed auth mode without declared credential keys.
|
|
50
50
|
- High-confidence secret or token material in source, README, package metadata, or fixtures.
|
|
51
|
+
- SDK-native source blockers: prefixed Provider ids, `vendor/` SDK shims or imports, raw `.describe()` prose instead of `describeKey`, raw global `fetch()` calls, and excessive `as Type` assertions.
|
|
51
52
|
|
|
52
|
-
Warnings do not fail the command, but they should be addressed when practical. For example, the generated starter `ping` operation warns because it is not a real upstream-backed bounty Operation.
|
|
53
|
+
Warnings do not fail the command, but they should be addressed when practical. For example, the generated starter `ping` operation warns because it is not a real upstream-backed bounty Operation. SDK-native warnings also flag moderate `as Type` assertion counts and credentialed Providers that never reference `ctx.credential`.
|
|
53
54
|
|
|
54
55
|
## Safe local smoke evidence
|
|
55
56
|
|
package/bin/apifuse-check.ts
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
|
|
3
|
-
import { existsSync, readFileSync, statSync } from "node:fs";
|
|
3
|
+
import { existsSync, readdirSync, readFileSync, statSync } from "node:fs";
|
|
4
4
|
import { dirname, resolve } from "node:path";
|
|
5
5
|
import { pathToFileURL } from "node:url";
|
|
6
6
|
|
|
7
7
|
import { z } from "zod";
|
|
8
8
|
|
|
9
9
|
import type { ProviderDefinition } from "../src";
|
|
10
|
-
import { lintProvider } from "../src/lint";
|
|
10
|
+
import { lintProvider, type ProviderLintMode } from "../src/lint";
|
|
11
11
|
import { safeParseSchemaSync } from "../src/schema";
|
|
12
12
|
|
|
13
13
|
const HELP_TEXT = `Usage: apifuse check [path]
|
|
14
|
-
Example: apifuse check providers/
|
|
14
|
+
Example: apifuse check providers/korea-air-quality
|
|
15
15
|
Default: apifuse check .`;
|
|
16
16
|
|
|
17
17
|
export type CheckResult = {
|
|
@@ -20,6 +20,10 @@ export type CheckResult = {
|
|
|
20
20
|
details?: string[];
|
|
21
21
|
};
|
|
22
22
|
|
|
23
|
+
export type RunChecksOptions = {
|
|
24
|
+
lintMode?: ProviderLintMode;
|
|
25
|
+
};
|
|
26
|
+
|
|
23
27
|
type SafeParseResult =
|
|
24
28
|
| { success: true; data: unknown }
|
|
25
29
|
| { success: false; error: unknown };
|
|
@@ -104,7 +108,10 @@ function resolveFromParents(inputPath: string): string {
|
|
|
104
108
|
}
|
|
105
109
|
}
|
|
106
110
|
|
|
107
|
-
export async function runChecks(
|
|
111
|
+
export async function runChecks(
|
|
112
|
+
providerRoot: string,
|
|
113
|
+
options: RunChecksOptions = {},
|
|
114
|
+
): Promise<CheckResult[]> {
|
|
108
115
|
const indexPath = resolve(providerRoot, "index.ts");
|
|
109
116
|
const dockerfilePath = resolve(providerRoot, "Dockerfile");
|
|
110
117
|
const packageJsonPath = resolve(providerRoot, "package.json");
|
|
@@ -113,19 +120,61 @@ export async function runChecks(providerRoot: string): Promise<CheckResult[]> {
|
|
|
113
120
|
? await import(pathToFileURL(indexPath).href)
|
|
114
121
|
: undefined;
|
|
115
122
|
const provider = assertProviderDefinition(providerModule?.default);
|
|
123
|
+
const providerSourceFiles = collectProviderSourceFiles(providerRoot);
|
|
116
124
|
|
|
117
125
|
return [
|
|
118
126
|
checkIndex(indexPath, provider),
|
|
119
127
|
checkOperations(provider),
|
|
120
128
|
checkFixtures(provider),
|
|
121
129
|
checkSchemas(provider),
|
|
122
|
-
checkAuthoringLint(provider),
|
|
130
|
+
checkAuthoringLint(provider, providerSourceFiles, options.lintMode),
|
|
123
131
|
checkProviderMetadata(provider),
|
|
124
132
|
checkDockerfile(dockerfilePath),
|
|
125
133
|
checkPackageJson(packageJsonPath),
|
|
126
134
|
];
|
|
127
135
|
}
|
|
128
136
|
|
|
137
|
+
function isScannableProviderSourceFile(relativePath: string): boolean {
|
|
138
|
+
return (
|
|
139
|
+
/\.(?:ts|tsx|js|jsx|mjs|cjs|sh|bash)$/.test(relativePath) ||
|
|
140
|
+
/(?:^|\/)Dockerfile(?:\.|$)/.test(relativePath) ||
|
|
141
|
+
/(?:^|\/)entrypoint(?:\.|$)/.test(relativePath)
|
|
142
|
+
);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
function collectProviderSourceFiles(
|
|
146
|
+
providerRoot: string,
|
|
147
|
+
): Record<string, string> {
|
|
148
|
+
const sources: Record<string, string> = {};
|
|
149
|
+
const skipDirectories = new Set([
|
|
150
|
+
".git",
|
|
151
|
+
"node_modules",
|
|
152
|
+
"dist",
|
|
153
|
+
"build",
|
|
154
|
+
".next",
|
|
155
|
+
]);
|
|
156
|
+
const visit = (directory: string) => {
|
|
157
|
+
for (const entry of readdirSync(directory, { withFileTypes: true })) {
|
|
158
|
+
const path = resolve(directory, entry.name);
|
|
159
|
+
if (entry.isDirectory()) {
|
|
160
|
+
if (!skipDirectories.has(entry.name)) {
|
|
161
|
+
visit(path);
|
|
162
|
+
}
|
|
163
|
+
continue;
|
|
164
|
+
}
|
|
165
|
+
if (
|
|
166
|
+
!entry.isFile() ||
|
|
167
|
+
!isScannableProviderSourceFile(path.slice(providerRoot.length + 1))
|
|
168
|
+
) {
|
|
169
|
+
continue;
|
|
170
|
+
}
|
|
171
|
+
sources[path.slice(providerRoot.length + 1)] = readFileSync(path, "utf8");
|
|
172
|
+
}
|
|
173
|
+
};
|
|
174
|
+
visit(providerRoot);
|
|
175
|
+
return sources;
|
|
176
|
+
}
|
|
177
|
+
|
|
129
178
|
function checkIndex(
|
|
130
179
|
indexPath: string,
|
|
131
180
|
provider: ProviderDefinition | undefined,
|
|
@@ -258,6 +307,8 @@ function checkSchemas(provider: ProviderDefinition | undefined): CheckResult {
|
|
|
258
307
|
|
|
259
308
|
function checkAuthoringLint(
|
|
260
309
|
provider: ProviderDefinition | undefined,
|
|
310
|
+
providerSourceFiles: Record<string, string>,
|
|
311
|
+
lintMode: ProviderLintMode = "official",
|
|
261
312
|
): CheckResult {
|
|
262
313
|
if (!provider) {
|
|
263
314
|
return {
|
|
@@ -266,7 +317,10 @@ function checkAuthoringLint(
|
|
|
266
317
|
};
|
|
267
318
|
}
|
|
268
319
|
|
|
269
|
-
const diagnostics = lintProvider(
|
|
320
|
+
const diagnostics = lintProvider(
|
|
321
|
+
{ ...provider, providerSourceFiles },
|
|
322
|
+
{ mode: lintMode },
|
|
323
|
+
);
|
|
270
324
|
const errors = diagnostics.filter(
|
|
271
325
|
(diagnostic) => diagnostic.level === "error",
|
|
272
326
|
);
|
package/bin/apifuse-dev.ts
CHANGED
|
@@ -9,16 +9,18 @@ import {
|
|
|
9
9
|
createEnvContext,
|
|
10
10
|
createHttpClient,
|
|
11
11
|
createProviderCache,
|
|
12
|
+
createProviderChoiceContext,
|
|
12
13
|
createStealthClient,
|
|
13
14
|
createSttClientFromEnv,
|
|
15
|
+
PROVIDER_RUNTIME_CHOICE_TOKEN_MASTER_SECRET_ENV,
|
|
14
16
|
ProviderError,
|
|
15
17
|
} from "../src";
|
|
16
|
-
import {
|
|
18
|
+
import { createMemoryProviderRuntimeState } from "../src/runtime/state";
|
|
17
19
|
import { createTraceContext } from "../src/runtime/trace";
|
|
18
20
|
import type { BrowserClient, ProviderContext } from "../src/types";
|
|
19
21
|
|
|
20
22
|
const HELP_TEXT = `Usage: apifuse dev [path]
|
|
21
|
-
Example: apifuse dev providers/
|
|
23
|
+
Example: apifuse dev providers/korea-air-quality
|
|
22
24
|
Default: apifuse dev .`;
|
|
23
25
|
|
|
24
26
|
export async function main() {
|
|
@@ -76,22 +78,35 @@ export async function main() {
|
|
|
76
78
|
export function createProviderContext(provider: ProviderDefinition): {
|
|
77
79
|
ctx: ProviderContext;
|
|
78
80
|
} {
|
|
81
|
+
const env = createEnvContext([
|
|
82
|
+
...(provider.secrets?.map((secret) => secret.name) ?? []),
|
|
83
|
+
PROVIDER_RUNTIME_CHOICE_TOKEN_MASTER_SECRET_ENV,
|
|
84
|
+
]);
|
|
85
|
+
const credential = createCredentialContext();
|
|
86
|
+
const state = createMemoryProviderRuntimeState();
|
|
79
87
|
const ctx: ProviderContext = {
|
|
80
|
-
env
|
|
81
|
-
credential
|
|
88
|
+
env,
|
|
89
|
+
credential,
|
|
82
90
|
auth: createUnsupportedAuthStub(),
|
|
83
91
|
browser:
|
|
84
92
|
provider.runtime === "browser"
|
|
85
93
|
? createBrowserClient({
|
|
94
|
+
allowedHosts: provider.allowedHosts,
|
|
86
95
|
engine: provider.browser?.engine ?? "playwright-stealth",
|
|
87
96
|
})
|
|
88
97
|
: createUnsupportedBrowserStub(),
|
|
89
98
|
http: createHttpClient(),
|
|
90
99
|
cache: createProviderCache({ providerId: provider.id }),
|
|
91
|
-
state
|
|
100
|
+
state,
|
|
92
101
|
trace: createTraceContext(),
|
|
93
102
|
stealth: createStealthClient("http://localhost"),
|
|
94
103
|
stt: createSttClientFromEnv(provider.stt),
|
|
104
|
+
choice: createProviderChoiceContext({
|
|
105
|
+
providerId: provider.id,
|
|
106
|
+
env,
|
|
107
|
+
credential,
|
|
108
|
+
state,
|
|
109
|
+
}),
|
|
95
110
|
};
|
|
96
111
|
|
|
97
112
|
return { ctx };
|
|
@@ -149,6 +164,7 @@ function shellSingleQuote(value: string): string {
|
|
|
149
164
|
function createUnsupportedBrowserStub(): BrowserClient {
|
|
150
165
|
return {
|
|
151
166
|
engine: "playwright-stealth",
|
|
167
|
+
async close() {},
|
|
152
168
|
async newPage() {
|
|
153
169
|
throw new ProviderError(
|
|
154
170
|
"Browser runtime is not enabled for this provider",
|
|
@@ -158,6 +174,33 @@ function createUnsupportedBrowserStub(): BrowserClient {
|
|
|
158
174
|
},
|
|
159
175
|
);
|
|
160
176
|
},
|
|
177
|
+
async rawPage() {
|
|
178
|
+
throw new ProviderError(
|
|
179
|
+
"Browser runtime is not enabled for this provider",
|
|
180
|
+
{
|
|
181
|
+
code: "BROWSER_RUNTIME_UNSUPPORTED",
|
|
182
|
+
fix: 'Set provider runtime to "browser" and APIFUSE__CDP_POOL__URL to use ctx.browser.rawPage',
|
|
183
|
+
},
|
|
184
|
+
);
|
|
185
|
+
},
|
|
186
|
+
async withIsolatedContext() {
|
|
187
|
+
throw new ProviderError(
|
|
188
|
+
"Browser runtime is not enabled for this provider",
|
|
189
|
+
{
|
|
190
|
+
code: "BROWSER_RUNTIME_UNSUPPORTED",
|
|
191
|
+
fix: 'Set provider runtime to "browser" to use ctx.browser.withIsolatedContext',
|
|
192
|
+
},
|
|
193
|
+
);
|
|
194
|
+
},
|
|
195
|
+
async solveChallenge() {
|
|
196
|
+
throw new ProviderError(
|
|
197
|
+
"Browser runtime is not enabled for this provider",
|
|
198
|
+
{
|
|
199
|
+
code: "BROWSER_RUNTIME_UNSUPPORTED",
|
|
200
|
+
fix: 'Set provider runtime to "browser" to use ctx.browser.solveChallenge',
|
|
201
|
+
},
|
|
202
|
+
);
|
|
203
|
+
},
|
|
161
204
|
};
|
|
162
205
|
}
|
|
163
206
|
|
package/bin/apifuse-perf.ts
CHANGED
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
type ApiFuseConfig,
|
|
11
11
|
createBypassProviderCache,
|
|
12
12
|
createHttpClient,
|
|
13
|
+
createProviderChoiceContext,
|
|
13
14
|
createStealthClient,
|
|
14
15
|
createSttClientFromEnv,
|
|
15
16
|
executeOperation,
|
|
@@ -29,6 +30,7 @@ import {
|
|
|
29
30
|
groupSpansByName,
|
|
30
31
|
type PerfStats,
|
|
31
32
|
} from "../src/runtime/perf";
|
|
33
|
+
import { createMemoryProviderRuntimeState } from "../src/runtime/state";
|
|
32
34
|
import {
|
|
33
35
|
createTraceContext,
|
|
34
36
|
resolveTraceContextOptions,
|
|
@@ -96,7 +98,7 @@ Options:
|
|
|
96
98
|
--help, -h show this help
|
|
97
99
|
|
|
98
100
|
Example:
|
|
99
|
-
apifuse perf providers/
|
|
101
|
+
apifuse perf providers/korea-air-quality --operation realtime --params '{"stationName":"jongno"}' --runs 5`;
|
|
100
102
|
|
|
101
103
|
export async function main() {
|
|
102
104
|
try {
|
|
@@ -688,24 +690,36 @@ function createBaseContext(options: {
|
|
|
688
690
|
upstream,
|
|
689
691
|
});
|
|
690
692
|
|
|
693
|
+
const env = {
|
|
694
|
+
get: (key: string) => process.env[key],
|
|
695
|
+
};
|
|
696
|
+
const credential = {
|
|
697
|
+
mode: "none" as const,
|
|
698
|
+
get: () => undefined,
|
|
699
|
+
getAll: () => ({}),
|
|
700
|
+
getAccessToken: () => undefined,
|
|
701
|
+
getScopes: () => [],
|
|
702
|
+
};
|
|
703
|
+
const state = createMemoryProviderRuntimeState();
|
|
691
704
|
return {
|
|
692
|
-
env
|
|
693
|
-
|
|
694
|
-
},
|
|
695
|
-
credential: {
|
|
696
|
-
mode: "none",
|
|
697
|
-
get: () => undefined,
|
|
698
|
-
getAll: () => ({}),
|
|
699
|
-
getAccessToken: () => undefined,
|
|
700
|
-
getScopes: () => [],
|
|
701
|
-
},
|
|
705
|
+
env,
|
|
706
|
+
credential,
|
|
707
|
+
request: { headers: {} },
|
|
702
708
|
http,
|
|
703
709
|
cache: createBypassProviderCache({ providerId: options.provider.id }),
|
|
710
|
+
state,
|
|
704
711
|
stealth,
|
|
705
712
|
browser: createBrowserStub(),
|
|
706
713
|
trace: options.traceContext,
|
|
707
714
|
auth: createAuthStub(),
|
|
708
715
|
stt: createSttClientFromEnv(options.provider.stt),
|
|
716
|
+
choice: createProviderChoiceContext({
|
|
717
|
+
providerId: options.provider.id,
|
|
718
|
+
env,
|
|
719
|
+
request: { headers: {} },
|
|
720
|
+
credential,
|
|
721
|
+
state,
|
|
722
|
+
}),
|
|
709
723
|
};
|
|
710
724
|
}
|
|
711
725
|
|
|
@@ -765,6 +779,7 @@ function createFixtureStealthClient(rawText: string): StealthClient {
|
|
|
765
779
|
function createBrowserStub(): BrowserClient {
|
|
766
780
|
return {
|
|
767
781
|
engine: "playwright-stealth",
|
|
782
|
+
async close() {},
|
|
768
783
|
async newPage() {
|
|
769
784
|
throw new ProviderError(
|
|
770
785
|
"Browser runtime is not supported by apifuse perf yet.",
|
|
@@ -773,6 +788,30 @@ function createBrowserStub(): BrowserClient {
|
|
|
773
788
|
},
|
|
774
789
|
);
|
|
775
790
|
},
|
|
791
|
+
async rawPage() {
|
|
792
|
+
throw new ProviderError(
|
|
793
|
+
"Browser runtime is not supported by apifuse perf yet.",
|
|
794
|
+
{
|
|
795
|
+
code: "BROWSER_RUNTIME_UNSUPPORTED",
|
|
796
|
+
},
|
|
797
|
+
);
|
|
798
|
+
},
|
|
799
|
+
async withIsolatedContext() {
|
|
800
|
+
throw new ProviderError(
|
|
801
|
+
"Browser runtime is not supported by apifuse perf yet.",
|
|
802
|
+
{
|
|
803
|
+
code: "BROWSER_RUNTIME_UNSUPPORTED",
|
|
804
|
+
},
|
|
805
|
+
);
|
|
806
|
+
},
|
|
807
|
+
async solveChallenge() {
|
|
808
|
+
throw new ProviderError(
|
|
809
|
+
"Browser runtime is not supported by apifuse perf yet.",
|
|
810
|
+
{
|
|
811
|
+
code: "BROWSER_RUNTIME_UNSUPPORTED",
|
|
812
|
+
},
|
|
813
|
+
);
|
|
814
|
+
},
|
|
776
815
|
};
|
|
777
816
|
}
|
|
778
817
|
|
package/bin/apifuse-record.ts
CHANGED
|
@@ -9,6 +9,7 @@ import { pathToFileURL } from "node:url";
|
|
|
9
9
|
import {
|
|
10
10
|
createBypassProviderCache,
|
|
11
11
|
createHttpClient,
|
|
12
|
+
createProviderChoiceContext,
|
|
12
13
|
createStealthClient,
|
|
13
14
|
createSttClientFromEnv,
|
|
14
15
|
executeOperation,
|
|
@@ -20,6 +21,7 @@ import {
|
|
|
20
21
|
TransportError,
|
|
21
22
|
ValidationError,
|
|
22
23
|
} from "../src";
|
|
24
|
+
import { createMemoryProviderRuntimeState } from "../src/runtime/state";
|
|
23
25
|
|
|
24
26
|
type CliArgs = {
|
|
25
27
|
append: boolean;
|
|
@@ -46,7 +48,7 @@ Options:
|
|
|
46
48
|
--help, -h show this help
|
|
47
49
|
|
|
48
50
|
Example:
|
|
49
|
-
apifuse record providers/
|
|
51
|
+
apifuse record providers/korea-air-quality --operation realtime --params '{"stationName":"jongno"}'`;
|
|
50
52
|
|
|
51
53
|
export async function main() {
|
|
52
54
|
try {
|
|
@@ -351,25 +353,40 @@ function createCaptureContext(provider: ProviderRuntime, baseUrl: string) {
|
|
|
351
353
|
},
|
|
352
354
|
);
|
|
353
355
|
|
|
356
|
+
const env = {
|
|
357
|
+
get: (key: string) => process.env[key],
|
|
358
|
+
};
|
|
359
|
+
const credential = {
|
|
360
|
+
mode: "none" as const,
|
|
361
|
+
get: () => undefined,
|
|
362
|
+
getAll: () => ({}),
|
|
363
|
+
getAccessToken: () => undefined,
|
|
364
|
+
getScopes: () => [],
|
|
365
|
+
};
|
|
366
|
+
const state = createMemoryProviderRuntimeState();
|
|
354
367
|
const ctx: ProviderContext = {
|
|
355
|
-
env
|
|
356
|
-
|
|
357
|
-
},
|
|
358
|
-
credential: {
|
|
359
|
-
mode: "none",
|
|
360
|
-
get: () => undefined,
|
|
361
|
-
getAll: () => ({}),
|
|
362
|
-
getAccessToken: () => undefined,
|
|
363
|
-
getScopes: () => [],
|
|
364
|
-
},
|
|
368
|
+
env,
|
|
369
|
+
credential,
|
|
370
|
+
request: { headers: {} },
|
|
365
371
|
http,
|
|
366
372
|
cache: createBypassProviderCache({ providerId: provider.id }),
|
|
373
|
+
state,
|
|
367
374
|
stealth,
|
|
368
375
|
browser: {
|
|
369
376
|
engine: "playwright-stealth",
|
|
377
|
+
close: async () => {},
|
|
370
378
|
newPage: async () => {
|
|
371
379
|
throw new Error("Browser client is not available in apifuse record.");
|
|
372
380
|
},
|
|
381
|
+
rawPage: async () => {
|
|
382
|
+
throw new Error("Browser client is not available in apifuse record.");
|
|
383
|
+
},
|
|
384
|
+
withIsolatedContext: async () => {
|
|
385
|
+
throw new Error("Browser client is not available in apifuse record.");
|
|
386
|
+
},
|
|
387
|
+
solveChallenge: async () => {
|
|
388
|
+
throw new Error("Browser client is not available in apifuse record.");
|
|
389
|
+
},
|
|
373
390
|
},
|
|
374
391
|
trace: {
|
|
375
392
|
span: async (_name, fn) => fn(),
|
|
@@ -380,6 +397,13 @@ function createCaptureContext(provider: ProviderRuntime, baseUrl: string) {
|
|
|
380
397
|
},
|
|
381
398
|
},
|
|
382
399
|
stt: createSttClientFromEnv(provider.stt),
|
|
400
|
+
choice: createProviderChoiceContext({
|
|
401
|
+
providerId: provider.id,
|
|
402
|
+
env,
|
|
403
|
+
request: { headers: {} },
|
|
404
|
+
credential,
|
|
405
|
+
state,
|
|
406
|
+
}),
|
|
383
407
|
};
|
|
384
408
|
|
|
385
409
|
return {
|