@apifuse/provider-sdk 2.2.0-beta.1 → 2.2.0-beta.11
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 +106 -0
- package/CHANGELOG.md +41 -0
- package/README.md +5 -1
- package/SUBMISSION.md +1 -1
- package/bin/apifuse-check.ts +44 -59
- package/bin/apifuse-create.ts +1 -1
- package/bin/apifuse-dev.ts +27 -52
- package/bin/apifuse-pack-check.ts +14 -0
- package/bin/apifuse-pack-smoke.ts +22 -81
- package/bin/apifuse-pack-types.ts +266 -0
- package/bin/apifuse-perf.ts +45 -127
- package/bin/apifuse-record.ts +53 -70
- package/bin/apifuse-submit-check.ts +510 -45
- package/bin/apifuse-sync-assets.ts +117 -0
- package/bin/apifuse.ts +1 -1
- package/bin/submit-check-delimited-text.ts +50 -0
- package/bin/submit-check-xml-semantics.ts +204 -0
- package/bin/submit-check-xml.ts +134 -0
- package/dist/auth-turn/index.d.ts +3 -3
- package/dist/auth.d.ts +2 -2
- package/dist/auth.js +9 -18
- package/dist/ceremonies/index.d.ts +1 -1
- package/dist/ceremonies/index.js +8 -18
- 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 +149 -8
- package/dist/config/loader.js +378 -89
- package/dist/contract-serialization.d.ts +2 -2
- package/dist/contract-serialization.js +3 -6
- package/dist/contract-types.d.ts +2 -2
- package/dist/contract.d.ts +3 -3
- package/dist/contract.js +4 -6
- package/dist/define.d.ts +8 -1
- package/dist/define.js +119 -122
- package/dist/dev.d.ts +1 -1
- package/dist/dev.js +1 -1
- package/dist/errors.d.ts +4 -1
- package/dist/errors.js +48 -0
- package/dist/i18n/catalog.d.ts +2 -2
- package/dist/i18n/catalog.js +4 -10
- package/dist/i18n/index.d.ts +2 -2
- package/dist/i18n/index.js +2 -2
- package/dist/i18n/keys.d.ts +2 -2
- package/dist/index.d.ts +44 -42
- package/dist/index.js +39 -37
- package/dist/lint.js +8 -15
- package/dist/provider.d.ts +11 -11
- package/dist/provider.js +9 -9
- package/dist/public-schema-field-lint.d.ts +1 -1
- package/dist/recipes/gov-api.js +1 -1
- package/dist/runtime/auth-flow.d.ts +1 -1
- package/dist/runtime/auth-flow.js +3 -3
- package/dist/runtime/browser.d.ts +1 -1
- package/dist/runtime/browser.js +15 -29
- package/dist/runtime/cache.d.ts +1 -1
- package/dist/runtime/cache.js +4 -8
- package/dist/runtime/choice.d.ts +1 -1
- package/dist/runtime/choice.js +31 -35
- package/dist/runtime/credential.d.ts +1 -1
- package/dist/runtime/credential.js +1 -1
- package/dist/runtime/env.d.ts +1 -1
- package/dist/runtime/executor.d.ts +1 -1
- package/dist/runtime/executor.js +15 -3
- package/dist/runtime/http.d.ts +2 -2
- package/dist/runtime/http.js +144 -348
- package/dist/runtime/insights.d.ts +1 -1
- package/dist/runtime/insights.js +6 -13
- package/dist/runtime/instrumentation.d.ts +2 -2
- package/dist/runtime/instrumentation.js +56 -19
- package/dist/runtime/keyring.js +1 -1
- package/dist/runtime/namespace.js +1 -1
- package/dist/runtime/otlp.d.ts +1 -1
- package/dist/runtime/perf.d.ts +1 -1
- package/dist/runtime/provider.d.ts +1 -1
- package/dist/runtime/provider.js +1 -2
- package/dist/runtime/proxy-errors.d.ts +1 -1
- package/dist/runtime/proxy-errors.js +9 -7
- package/dist/runtime/proxy-nodemaven.d.ts +35 -0
- package/dist/runtime/proxy-nodemaven.js +128 -0
- package/dist/runtime/proxy-retry-policy.d.ts +40 -0
- package/dist/runtime/proxy-retry-policy.js +326 -0
- package/dist/runtime/proxy-telemetry.d.ts +2 -1
- package/dist/runtime/proxy-telemetry.js +55 -52
- package/dist/runtime/redis.d.ts +1 -1
- package/dist/runtime/redis.js +2 -4
- package/dist/runtime/request-options.d.ts +1 -1
- package/dist/runtime/secrets.d.ts +27 -0
- package/dist/runtime/secrets.js +51 -0
- package/dist/runtime/state.d.ts +2 -2
- package/dist/runtime/state.js +15 -4
- package/dist/runtime/stealth.d.ts +2 -2
- package/dist/runtime/stealth.js +108 -212
- package/dist/runtime/stt.d.ts +1 -1
- package/dist/runtime/stt.js +11 -15
- package/dist/runtime/trace.d.ts +2 -2
- package/dist/runtime/trace.js +2 -4
- package/dist/runtime/waterfall.d.ts +1 -1
- package/dist/schema.d.ts +1 -1
- package/dist/schema.js +7 -15
- package/dist/serve.d.ts +1 -1
- package/dist/serve.js +1 -1
- package/dist/server/index.d.ts +7 -7
- package/dist/server/index.js +6 -6
- package/dist/server/self-test-redaction.d.ts +1 -1
- package/dist/server/self-test-redaction.js +1 -1
- package/dist/server/self-test.d.ts +104 -3
- package/dist/server/self-test.js +673 -115
- package/dist/server/serve.d.ts +105 -4
- package/dist/server/serve.js +588 -80
- package/dist/server/types.d.ts +10 -9
- package/dist/server/types.js +3 -7
- package/dist/stateful/errors.d.ts +14 -0
- package/dist/stateful/errors.js +14 -0
- package/dist/stateful/http-provider-event-emitter.d.ts +40 -0
- package/dist/stateful/http-provider-event-emitter.js +237 -0
- package/dist/stateful/http-session-owner-registry.d.ts +44 -0
- package/dist/stateful/http-session-owner-registry.js +210 -0
- package/dist/stateful/index.d.ts +18 -0
- package/dist/stateful/index.js +18 -0
- package/dist/stateful/provider-event-delivery-failures.d.ts +32 -0
- package/dist/stateful/provider-event-delivery-failures.js +43 -0
- package/dist/stateful/provider-event-pipeline-metrics.d.ts +46 -0
- package/dist/stateful/provider-event-pipeline-metrics.js +48 -0
- package/dist/stateful/provider-event-pipeline.d.ts +50 -0
- package/dist/stateful/provider-event-pipeline.js +1 -0
- package/dist/stateful/provider-events.d.ts +101 -0
- package/dist/stateful/provider-events.js +289 -0
- package/dist/stateful/session-key.d.ts +15 -0
- package/dist/stateful/session-key.js +86 -0
- package/dist/stateful/stateful-provider-adapter-context.d.ts +5 -0
- package/dist/stateful/stateful-provider-adapter-context.js +42 -0
- package/dist/stateful/stateful-provider-adapter-metrics.d.ts +15 -0
- package/dist/stateful/stateful-provider-adapter-metrics.js +21 -0
- package/dist/stateful/stateful-provider-adapter.d.ts +98 -0
- package/dist/stateful/stateful-provider-adapter.js +287 -0
- package/dist/stateful/stateful-provider-observability.d.ts +62 -0
- package/dist/stateful/stateful-provider-observability.js +161 -0
- package/dist/stateful/stateful-provider-owner-forwarder.d.ts +41 -0
- package/dist/stateful/stateful-provider-owner-forwarder.js +207 -0
- package/dist/stateful/stateful-provider-runtime-context.d.ts +32 -0
- package/dist/stateful/stateful-provider-runtime-context.js +60 -0
- package/dist/stateful/stateful-provider-runtime-executor.d.ts +34 -0
- package/dist/stateful/stateful-provider-runtime-executor.js +52 -0
- package/dist/stateful/stateful-provider-session-routing.d.ts +71 -0
- package/dist/stateful/stateful-provider-session-routing.js +353 -0
- package/dist/stateful/stateful-provider-session-runtime.d.ts +98 -0
- package/dist/stateful/stateful-provider-session-runtime.js +245 -0
- package/dist/stateful-signing.d.ts +18 -0
- package/dist/stateful-signing.js +27 -0
- package/dist/stealth/profiles.d.ts +1 -1
- package/dist/stealth/profiles.js +5 -14
- package/dist/stream.d.ts +1 -1
- package/dist/testing/index.d.ts +2 -2
- package/dist/testing/index.js +2 -2
- package/dist/testing/run.d.ts +1 -1
- package/dist/testing/run.js +7 -14
- package/dist/types.d.ts +87 -1
- package/dist/user-input.d.ts +30 -0
- package/dist/user-input.js +66 -0
- package/package.json +14 -5
- package/src/auth-turn/index.ts +1 -1
- package/src/auth.ts +28 -86
- package/src/ceremonies/index.ts +24 -78
- 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 +543 -208
- package/src/contract-serialization.ts +5 -11
- package/src/contract-types.ts +2 -2
- package/src/contract.ts +12 -28
- package/src/define.ts +247 -505
- package/src/dev.ts +4 -9
- package/src/errors.ts +58 -5
- package/src/i18n/catalog.ts +10 -32
- package/src/i18n/index.ts +2 -2
- package/src/i18n/keys.ts +5 -11
- package/src/index.ts +49 -42
- package/src/lint.ts +89 -159
- package/src/provider.ts +15 -11
- package/src/public-schema-field-lint.ts +7 -33
- package/src/recipes/gov-api.ts +2 -5
- package/src/runtime/auth-flow.ts +5 -7
- package/src/runtime/browser.ts +64 -187
- package/src/runtime/cache.ts +20 -67
- package/src/runtime/choice.ts +79 -132
- package/src/runtime/credential.ts +2 -2
- package/src/runtime/env.ts +1 -1
- package/src/runtime/executor.ts +23 -20
- package/src/runtime/http.ts +195 -559
- package/src/runtime/insights.ts +15 -53
- package/src/runtime/instrumentation.ts +78 -65
- package/src/runtime/keyring.ts +7 -19
- package/src/runtime/namespace.ts +2 -7
- package/src/runtime/otlp.ts +12 -23
- package/src/runtime/perf.ts +1 -1
- package/src/runtime/provider.ts +4 -9
- package/src/runtime/proxy-errors.ts +29 -42
- package/src/runtime/proxy-nodemaven.ts +178 -0
- package/src/runtime/proxy-retry-policy.ts +469 -0
- package/src/runtime/proxy-telemetry.ts +79 -77
- package/src/runtime/redis.ts +4 -12
- package/src/runtime/request-options.ts +4 -13
- package/src/runtime/secrets.ts +64 -0
- package/src/runtime/state.ts +41 -110
- package/src/runtime/stealth.ts +162 -377
- package/src/runtime/stt.ts +38 -94
- package/src/runtime/trace.ts +14 -44
- package/src/runtime/waterfall.ts +5 -18
- package/src/schema.ts +23 -84
- package/src/serve.ts +1 -1
- package/src/server/index.ts +24 -7
- package/src/server/self-test-redaction.ts +2 -2
- package/src/server/self-test.ts +857 -132
- package/src/server/serve.ts +859 -266
- package/src/server/types.ts +7 -19
- package/src/stateful/README.md +146 -0
- package/src/stateful/errors.ts +23 -0
- package/src/stateful/http-provider-event-emitter.ts +314 -0
- package/src/stateful/http-session-owner-registry.ts +306 -0
- package/src/stateful/index.ts +18 -0
- package/src/stateful/provider-event-delivery-failures.ts +80 -0
- package/src/stateful/provider-event-pipeline-metrics.ts +95 -0
- package/src/stateful/provider-event-pipeline.ts +61 -0
- package/src/stateful/provider-events.ts +462 -0
- package/src/stateful/session-key.ts +111 -0
- package/src/stateful/stateful-provider-adapter-context.ts +59 -0
- package/src/stateful/stateful-provider-adapter-metrics.ts +48 -0
- package/src/stateful/stateful-provider-adapter.ts +562 -0
- package/src/stateful/stateful-provider-observability.ts +261 -0
- package/src/stateful/stateful-provider-owner-forwarder.ts +279 -0
- package/src/stateful/stateful-provider-runtime-context.ts +92 -0
- package/src/stateful/stateful-provider-runtime-executor.ts +96 -0
- package/src/stateful/stateful-provider-session-routing.ts +555 -0
- package/src/stateful/stateful-provider-session-runtime.ts +403 -0
- package/src/stateful-signing.ts +46 -0
- package/src/stealth/profiles.ts +10 -26
- package/src/stream.ts +8 -19
- package/src/testing/index.ts +2 -2
- package/src/testing/run.ts +19 -67
- package/src/types.ts +88 -1
- package/src/user-input.ts +118 -0
- 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
package/src/testing/run.ts
CHANGED
|
@@ -1,28 +1,23 @@
|
|
|
1
1
|
import { describe, expect, it } from "bun:test";
|
|
2
2
|
|
|
3
|
-
import { createProviderCache } from "../runtime/cache";
|
|
4
|
-
import { createTestProviderChoiceContext } from "../runtime/choice";
|
|
5
|
-
import { createMemoryProviderRuntimeState } from "../runtime/state";
|
|
6
|
-
import { createUnsupportedSttClient } from "../runtime/stt";
|
|
7
|
-
import { safeParseSchemaSync } from "../schema";
|
|
3
|
+
import { createProviderCache } from "../runtime/cache.js";
|
|
4
|
+
import { createTestProviderChoiceContext } from "../runtime/choice.js";
|
|
5
|
+
import { createMemoryProviderRuntimeState } from "../runtime/state.js";
|
|
6
|
+
import { createUnsupportedSttClient } from "../runtime/stt.js";
|
|
7
|
+
import { safeParseSchemaSync } from "../schema.js";
|
|
8
8
|
import type {
|
|
9
9
|
AuthMode,
|
|
10
10
|
CredentialContext,
|
|
11
11
|
HttpResponse,
|
|
12
12
|
ProviderContext,
|
|
13
13
|
ProviderDefinition,
|
|
14
|
-
} from "../types";
|
|
14
|
+
} from "../types.js";
|
|
15
15
|
|
|
16
16
|
// Mirrors CONNECTOR_ID_REGEX in ../define.ts, which defineProvider() enforces.
|
|
17
17
|
// A single lowercase segment (no hyphen) is a valid id, so the trailing group
|
|
18
18
|
// is optional (`*`), matching providers like `kakaomap`, `kstartup`, `triple`.
|
|
19
19
|
const CONNECTOR_ID_REGEX = /^[a-z][a-z0-9]*(-[a-z][a-z0-9]*)*$/;
|
|
20
|
-
const VALID_AUTH_MODES = [
|
|
21
|
-
"none",
|
|
22
|
-
"platform-managed",
|
|
23
|
-
"credentials",
|
|
24
|
-
"oauth2",
|
|
25
|
-
] as const;
|
|
20
|
+
const VALID_AUTH_MODES = ["none", "platform-managed", "credentials", "oauth2"] as const;
|
|
26
21
|
const UPDATE_SNAPSHOT_ARGS = new Set(["-u", "--update-snapshots"]);
|
|
27
22
|
|
|
28
23
|
export interface StandardTestsManifest {
|
|
@@ -118,9 +113,7 @@ function inferFixtureDir(providerId: string): string {
|
|
|
118
113
|
.find((file) => file !== undefined);
|
|
119
114
|
|
|
120
115
|
if (testFile) {
|
|
121
|
-
const pathname = testFile.startsWith("file://")
|
|
122
|
-
? new URL(testFile).pathname
|
|
123
|
-
: testFile;
|
|
116
|
+
const pathname = testFile.startsWith("file://") ? new URL(testFile).pathname : testFile;
|
|
124
117
|
return `${pathname.replace(/\/[^/]+$/, "")}/../__fixtures__`;
|
|
125
118
|
}
|
|
126
119
|
|
|
@@ -138,10 +131,7 @@ function jsonResponse(data: unknown): HttpResponse {
|
|
|
138
131
|
json: async <_T = unknown>() => JSON.parse(JSON.stringify(data)),
|
|
139
132
|
text: async () => body,
|
|
140
133
|
arrayBuffer: async () =>
|
|
141
|
-
bodyBytes.buffer.slice(
|
|
142
|
-
bodyBytes.byteOffset,
|
|
143
|
-
bodyBytes.byteOffset + bodyBytes.byteLength,
|
|
144
|
-
),
|
|
134
|
+
bodyBytes.buffer.slice(bodyBytes.byteOffset, bodyBytes.byteOffset + bodyBytes.byteLength),
|
|
145
135
|
bytes: async () => bodyBytes.slice(0),
|
|
146
136
|
};
|
|
147
137
|
}
|
|
@@ -184,16 +174,14 @@ function createSnapshotContext(rawFixture: unknown): ProviderContext {
|
|
|
184
174
|
engine: "playwright-stealth",
|
|
185
175
|
newPage: async () => unsupported("ctx.browser.newPage"),
|
|
186
176
|
rawPage: async () => unsupported("ctx.browser.rawPage"),
|
|
187
|
-
withIsolatedContext: async () =>
|
|
188
|
-
unsupported("ctx.browser.withIsolatedContext"),
|
|
177
|
+
withIsolatedContext: async () => unsupported("ctx.browser.withIsolatedContext"),
|
|
189
178
|
solveChallenge: async () => unsupported("ctx.browser.solveChallenge"),
|
|
190
179
|
},
|
|
191
180
|
trace: {
|
|
192
181
|
span: async (_name, fn) => fn(),
|
|
193
182
|
},
|
|
194
183
|
auth: {
|
|
195
|
-
requestField: async (name) =>
|
|
196
|
-
unsupported(`ctx.auth.requestField(${name})`),
|
|
184
|
+
requestField: async (name) => unsupported(`ctx.auth.requestField(${name})`),
|
|
197
185
|
},
|
|
198
186
|
stt: createUnsupportedSttClient(
|
|
199
187
|
"Standard test snapshot context does not support ctx.stt.transcribe",
|
|
@@ -292,11 +280,7 @@ function parseSchemaFixture(
|
|
|
292
280
|
operationName,
|
|
293
281
|
fieldName,
|
|
294
282
|
fixture,
|
|
295
|
-
safeParseSchemaSync(
|
|
296
|
-
schema,
|
|
297
|
-
fixture,
|
|
298
|
-
`operations.${operationName}.fixtures.${fieldName}`,
|
|
299
|
-
),
|
|
283
|
+
safeParseSchemaSync(schema, fixture, `operations.${operationName}.fixtures.${fieldName}`),
|
|
300
284
|
);
|
|
301
285
|
}
|
|
302
286
|
|
|
@@ -322,40 +306,20 @@ export function runStandardTests(
|
|
|
322
306
|
|
|
323
307
|
for (const [operationName, op] of operations) {
|
|
324
308
|
if (op.fixtures?.request !== undefined) {
|
|
325
|
-
parseSchemaFixture(
|
|
326
|
-
operationName,
|
|
327
|
-
"request",
|
|
328
|
-
op.input,
|
|
329
|
-
op.fixtures.request,
|
|
330
|
-
);
|
|
309
|
+
parseSchemaFixture(operationName, "request", op.input, op.fixtures.request);
|
|
331
310
|
}
|
|
332
311
|
|
|
333
312
|
if (op.fixtures?.response !== undefined) {
|
|
334
|
-
parseSchemaFixture(
|
|
335
|
-
operationName,
|
|
336
|
-
"response",
|
|
337
|
-
op.output,
|
|
338
|
-
op.fixtures.response,
|
|
339
|
-
);
|
|
313
|
+
parseSchemaFixture(operationName, "response", op.output, op.fixtures.response);
|
|
340
314
|
}
|
|
341
315
|
|
|
342
316
|
if (isFixtureEnvelope(rawFixture)) {
|
|
343
317
|
if (rawFixture.request !== undefined) {
|
|
344
|
-
parseSchemaFixture(
|
|
345
|
-
operationName,
|
|
346
|
-
"request",
|
|
347
|
-
op.input,
|
|
348
|
-
rawFixture.request,
|
|
349
|
-
);
|
|
318
|
+
parseSchemaFixture(operationName, "request", op.input, rawFixture.request);
|
|
350
319
|
}
|
|
351
320
|
|
|
352
321
|
if (rawFixture.response !== undefined) {
|
|
353
|
-
parseSchemaFixture(
|
|
354
|
-
operationName,
|
|
355
|
-
"response",
|
|
356
|
-
op.output,
|
|
357
|
-
rawFixture.response,
|
|
358
|
-
);
|
|
322
|
+
parseSchemaFixture(operationName, "response", op.output, rawFixture.response);
|
|
359
323
|
}
|
|
360
324
|
}
|
|
361
325
|
}
|
|
@@ -411,21 +375,11 @@ export function runStandardTests(
|
|
|
411
375
|
it("operation schemas can parse fixture data", () => {
|
|
412
376
|
for (const [operationName, op] of operations) {
|
|
413
377
|
if (op.fixtures?.request !== undefined && op.input) {
|
|
414
|
-
parseSchemaFixture(
|
|
415
|
-
operationName,
|
|
416
|
-
"request",
|
|
417
|
-
op.input,
|
|
418
|
-
op.fixtures.request,
|
|
419
|
-
);
|
|
378
|
+
parseSchemaFixture(operationName, "request", op.input, op.fixtures.request);
|
|
420
379
|
}
|
|
421
380
|
|
|
422
381
|
if (op.fixtures?.response !== undefined && op.output) {
|
|
423
|
-
parseSchemaFixture(
|
|
424
|
-
operationName,
|
|
425
|
-
"response",
|
|
426
|
-
op.output,
|
|
427
|
-
op.fixtures.response,
|
|
428
|
-
);
|
|
382
|
+
parseSchemaFixture(operationName, "response", op.output, op.fixtures.response);
|
|
429
383
|
}
|
|
430
384
|
|
|
431
385
|
expect(operationName).toBeTruthy();
|
|
@@ -471,9 +425,7 @@ export function runStandardTests(
|
|
|
471
425
|
await Bun.write(snapshotPath, serialized);
|
|
472
426
|
}
|
|
473
427
|
|
|
474
|
-
const expected: unknown = JSON.parse(
|
|
475
|
-
await Bun.file(snapshotPath).text(),
|
|
476
|
-
);
|
|
428
|
+
const expected: unknown = JSON.parse(await Bun.file(snapshotPath).text());
|
|
477
429
|
expect(actual).toEqual(expected);
|
|
478
430
|
});
|
|
479
431
|
}
|
package/src/types.ts
CHANGED
|
@@ -769,7 +769,25 @@ export type ProviderAccessVisibility = "public" | "early_access";
|
|
|
769
769
|
|
|
770
770
|
export type ProviderProxyMode = "disabled" | "optional" | "required";
|
|
771
771
|
|
|
772
|
-
|
|
772
|
+
/**
|
|
773
|
+
* Proxy egress vendors. These are FOUR DISTINCT services — do not conflate them
|
|
774
|
+
* (a common mistake because the names collide with a well-known rebrand):
|
|
775
|
+
*
|
|
776
|
+
* - `smartproxy` — **api.smartproxy.org**, a residential proxy with an IP
|
|
777
|
+
* *extraction/allocation* API (app_key → a pool of raw `ip:port` CONNECT
|
|
778
|
+
* endpoints). This is our own vendor. It is NOT the company formerly named
|
|
779
|
+
* "Smartproxy". Credentials: `APIFUSE__PROXY__SMARTPROXY_APP_KEY`.
|
|
780
|
+
* - `nodemaven` — **gate.nodemaven.com**, a *gateway* proxy with static
|
|
781
|
+
* credentials; geo/session encoded in the username, no allocation API.
|
|
782
|
+
* - `decodo` — **decodo.com**, the *gateway* proxy that was named "Smartproxy"
|
|
783
|
+
* (smartproxy.com) before its 2025 rebrand to Decodo. Sticky sessions via
|
|
784
|
+
* username params. A different company from `smartproxy` above.
|
|
785
|
+
* **@deprecated** — unused; no managed adapter. Use `smartproxy`/`nodemaven`,
|
|
786
|
+
* or the `APIFUSE__PROXY__URL` bring-your-own escape hatch.
|
|
787
|
+
* - `custom` — **@deprecated** bring-your-own static proxy URL marker. The
|
|
788
|
+
* `APIFUSE__PROXY__URL` env still works without declaring this value.
|
|
789
|
+
*/
|
|
790
|
+
export type ProviderProxyProvider = "smartproxy" | "nodemaven" | "decodo" | "custom";
|
|
773
791
|
|
|
774
792
|
export type ProviderProxySessionAffinity =
|
|
775
793
|
| "request"
|
|
@@ -783,7 +801,18 @@ export interface ProviderProxyPolicy {
|
|
|
783
801
|
* certificate verification, and vendor allocator endpoints are SDK-owned.
|
|
784
802
|
*/
|
|
785
803
|
mode: ProviderProxyMode;
|
|
804
|
+
/**
|
|
805
|
+
* @deprecated Use `providers: [...]` to declare an ordered vendor fallback
|
|
806
|
+
* chain. A single-element `providers` list is equivalent to this field.
|
|
807
|
+
*/
|
|
786
808
|
provider?: ProviderProxyProvider;
|
|
809
|
+
/**
|
|
810
|
+
* Ordered proxy-vendor fallback chain. The SDK tries each vendor in order and
|
|
811
|
+
* fails over to the next when a vendor lacks credentials or its allocation /
|
|
812
|
+
* transport is exhausted. When omitted, `provider` (or the platform default)
|
|
813
|
+
* is used as a single-vendor chain.
|
|
814
|
+
*/
|
|
815
|
+
providers?: ProviderProxyProvider[];
|
|
787
816
|
geo?: {
|
|
788
817
|
/** ISO 3166-1 alpha-2 country code, for example KR or US. */
|
|
789
818
|
country?: Iso3166Alpha2CountryCode;
|
|
@@ -1759,6 +1788,19 @@ export interface OperationDefinition<
|
|
|
1759
1788
|
TInput extends SchemaLike = SchemaLike,
|
|
1760
1789
|
TOutput extends SchemaLike = SchemaLike,
|
|
1761
1790
|
> {
|
|
1791
|
+
/**
|
|
1792
|
+
* Short English display title for the operation. The SDK passes it through
|
|
1793
|
+
* verbatim; the APIFuse registry derives the operation's en locale title
|
|
1794
|
+
* baseline from it (`docs.titleKey` remains available as an explicit key
|
|
1795
|
+
* override).
|
|
1796
|
+
*/
|
|
1797
|
+
title?: string;
|
|
1798
|
+
/**
|
|
1799
|
+
* Raw English operation description. The SDK passes it through verbatim;
|
|
1800
|
+
* keyed descriptions via `descriptionKey` remain the primary flow, and
|
|
1801
|
+
* provider lint rules for raw prose descriptions still apply.
|
|
1802
|
+
*/
|
|
1803
|
+
description?: string;
|
|
1762
1804
|
descriptionKey?: ProviderLocaleKeyInput;
|
|
1763
1805
|
docs?: OperationDocMeta;
|
|
1764
1806
|
whenToUseKeys?: readonly ProviderLocaleKeyInput[];
|
|
@@ -1797,10 +1839,55 @@ export interface OperationDefinition<
|
|
|
1797
1839
|
healthCheckUnsupported?: HealthCheckUnsupported;
|
|
1798
1840
|
}
|
|
1799
1841
|
|
|
1842
|
+
/**
|
|
1843
|
+
* Author-declared deployment overrides accepted as the optional top-level
|
|
1844
|
+
* `deployment` key on `defineProvider()`.
|
|
1845
|
+
*
|
|
1846
|
+
* The SDK passes this object through VERBATIM onto the returned provider
|
|
1847
|
+
* definition — it is typed here but deliberately not deep-validated: the
|
|
1848
|
+
* APIFuse registry builder owns deployment validation and resolves omitted
|
|
1849
|
+
* fields against the runtime deployment profiles. The shape mirrors the
|
|
1850
|
+
* registry's `ProviderDeploymentOverrides` contract; every field is
|
|
1851
|
+
* optional. Note that the deployment `runtime` axis
|
|
1852
|
+
* (`shared`/`dedicated`/`browser`) is distinct from the provider execution
|
|
1853
|
+
* `runtime` (`standard`/`shared`/`browser`).
|
|
1854
|
+
*/
|
|
1855
|
+
export interface ProviderDeploymentOverrides {
|
|
1856
|
+
runtime?: "shared" | "dedicated" | "browser";
|
|
1857
|
+
language?: "typescript" | "python";
|
|
1858
|
+
replicas?: number;
|
|
1859
|
+
hpa?: {
|
|
1860
|
+
enabled: boolean;
|
|
1861
|
+
minReplicas?: number;
|
|
1862
|
+
maxReplicas?: number;
|
|
1863
|
+
targetCPUUtilizationPercentage?: number;
|
|
1864
|
+
};
|
|
1865
|
+
resources?: {
|
|
1866
|
+
cpu: string;
|
|
1867
|
+
memory: string;
|
|
1868
|
+
};
|
|
1869
|
+
cache?: {
|
|
1870
|
+
redis?: {
|
|
1871
|
+
enabled: boolean;
|
|
1872
|
+
url?: string;
|
|
1873
|
+
};
|
|
1874
|
+
};
|
|
1875
|
+
network?: {
|
|
1876
|
+
additionalTcpPorts?: number[];
|
|
1877
|
+
};
|
|
1878
|
+
buildContext?: string;
|
|
1879
|
+
}
|
|
1880
|
+
|
|
1800
1881
|
export interface ProviderDefinition {
|
|
1801
1882
|
id: string;
|
|
1802
1883
|
version: string;
|
|
1803
1884
|
runtime: "standard" | "shared" | "browser";
|
|
1885
|
+
/**
|
|
1886
|
+
* Optional deployment overrides, passed through verbatim from
|
|
1887
|
+
* `defineProvider({ deployment })`. Validation and profile resolution are
|
|
1888
|
+
* owned by the APIFuse registry builder, not the SDK.
|
|
1889
|
+
*/
|
|
1890
|
+
deployment?: ProviderDeploymentOverrides;
|
|
1804
1891
|
allowedHosts?: string[];
|
|
1805
1892
|
stealth?: {
|
|
1806
1893
|
profile: string;
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
// Official cross-provider contract for user-input round-trips.
|
|
2
|
+
//
|
|
3
|
+
// Doctrine (born from the 2026-07-20 CatchTable reserve incident): an
|
|
4
|
+
// operation MUST NOT dead-end on a problem the end user can resolve by
|
|
5
|
+
// choosing among live options. Instead of throwing, the provider returns a
|
|
6
|
+
// SUCCESSFUL payload with `status: "needs_input"` that carries everything a
|
|
7
|
+
// consumer-side agent needs to relay the choice verbatim and retry:
|
|
8
|
+
//
|
|
9
|
+
// - `required_selections`: only the still-pending questions, each with
|
|
10
|
+
// human-readable `label`s and `valid_options` the agent shows the user
|
|
11
|
+
// as-is. The agent never chooses on the user's behalf.
|
|
12
|
+
// - `selected_options`: selections already settled, echoed so the follow-up
|
|
13
|
+
// call keeps them without the agent reconstructing anything.
|
|
14
|
+
// - a fresh provider-specific state token (e.g. `reservation_state`) minted
|
|
15
|
+
// at response time, so the retry never races an expired token.
|
|
16
|
+
//
|
|
17
|
+
// Keeping this success-shaped (instead of error `details`) is deliberate:
|
|
18
|
+
// consumer error-shaping layers routinely strip error metadata, and a model
|
|
19
|
+
// that only sees "error" narrates failure to the user. Complex recovery
|
|
20
|
+
// logic belongs to the system, not the model.
|
|
21
|
+
//
|
|
22
|
+
// Deliberately ABSENT: retry templates, next-action routing, or any other
|
|
23
|
+
// agent choreography. Provider payloads carry upstream-backed data only; how
|
|
24
|
+
// to phrase the ask and shape the retry call is the consumer's contract
|
|
25
|
+
// (apifuse#1030). The retry is fully determined by data: copy the echoed
|
|
26
|
+
// selected_options, add the user's new answers, resend with the fresh state.
|
|
27
|
+
|
|
28
|
+
export const NEEDS_INPUT_STATUS = "needs_input" as const;
|
|
29
|
+
|
|
30
|
+
export interface ProviderSelectionOption {
|
|
31
|
+
readonly selection_value: string;
|
|
32
|
+
readonly label: string;
|
|
33
|
+
readonly [extra: string]: unknown;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export interface ProviderRequiredSelection {
|
|
37
|
+
readonly selection_key: string;
|
|
38
|
+
readonly label: string;
|
|
39
|
+
readonly required: boolean;
|
|
40
|
+
readonly selection_type?: string;
|
|
41
|
+
readonly valid_options: readonly ProviderSelectionOption[];
|
|
42
|
+
readonly [extra: string]: unknown;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export interface ProviderSelectedOption {
|
|
46
|
+
readonly selection_key: string;
|
|
47
|
+
readonly selection_value: string;
|
|
48
|
+
/** Free-text answer for text-kind selections. */
|
|
49
|
+
readonly text?: string;
|
|
50
|
+
/** Quantity for quantity-kind selections. */
|
|
51
|
+
readonly quantity?: number;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export interface ProviderNeedsInputPayload {
|
|
55
|
+
readonly status: typeof NEEDS_INPUT_STATUS;
|
|
56
|
+
readonly required_selections: readonly ProviderRequiredSelection[];
|
|
57
|
+
readonly selected_options?: readonly ProviderSelectedOption[];
|
|
58
|
+
/** Provider-specific fresh state token(s), e.g. `reservation_state`. */
|
|
59
|
+
readonly [extra: string]: unknown;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
63
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function isSelectionOption(value: unknown): value is ProviderSelectionOption {
|
|
67
|
+
return (
|
|
68
|
+
isRecord(value) &&
|
|
69
|
+
typeof value.selection_value === "string" &&
|
|
70
|
+
typeof value.label === "string"
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function isRequiredSelection(
|
|
75
|
+
value: unknown,
|
|
76
|
+
): value is ProviderRequiredSelection {
|
|
77
|
+
return (
|
|
78
|
+
isRecord(value) &&
|
|
79
|
+
typeof value.selection_key === "string" &&
|
|
80
|
+
typeof value.label === "string" &&
|
|
81
|
+
typeof value.required === "boolean" &&
|
|
82
|
+
Array.isArray(value.valid_options) &&
|
|
83
|
+
value.valid_options.every(isSelectionOption)
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function isSelectedOption(value: unknown): value is ProviderSelectedOption {
|
|
88
|
+
return (
|
|
89
|
+
isRecord(value) &&
|
|
90
|
+
typeof value.selection_key === "string" &&
|
|
91
|
+
typeof value.selection_value === "string"
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export function isProviderNeedsInputPayload(
|
|
96
|
+
value: unknown,
|
|
97
|
+
): value is ProviderNeedsInputPayload {
|
|
98
|
+
if (!isRecord(value)) {
|
|
99
|
+
return false;
|
|
100
|
+
}
|
|
101
|
+
if (
|
|
102
|
+
value.status !== NEEDS_INPUT_STATUS ||
|
|
103
|
+
!Array.isArray(value.required_selections) ||
|
|
104
|
+
!value.required_selections.every(isRequiredSelection)
|
|
105
|
+
) {
|
|
106
|
+
return false;
|
|
107
|
+
}
|
|
108
|
+
// A needs_input with nothing to ask AND nothing settled to echo is a
|
|
109
|
+
// no-op dead end — reject it so providers cannot ship it accidentally.
|
|
110
|
+
if (value.required_selections.length > 0) {
|
|
111
|
+
return true;
|
|
112
|
+
}
|
|
113
|
+
return (
|
|
114
|
+
Array.isArray(value.selected_options) &&
|
|
115
|
+
value.selected_options.length > 0 &&
|
|
116
|
+
value.selected_options.every(isSelectedOption)
|
|
117
|
+
);
|
|
118
|
+
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
@AGENTS.md
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
@AGENTS.md
|
/package/dist/cli/templates/provider/{skills → .agents/skills}/fixtures-and-recording/SKILL.md.tpl
RENAMED
|
File without changes
|
|
File without changes
|
/package/dist/cli/templates/provider/{skills → .agents/skills}/normalization-standards/SKILL.md.tpl
RENAMED
|
File without changes
|
/package/dist/cli/templates/provider/{skills → .agents/skills}/pagination-and-counts/SKILL.md.tpl
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
/package/src/cli/templates/provider/{skills → .agents/skills}/fixtures-and-recording/SKILL.md.tpl
RENAMED
|
File without changes
|
|
File without changes
|
/package/src/cli/templates/provider/{skills → .agents/skills}/normalization-standards/SKILL.md.tpl
RENAMED
|
File without changes
|
/package/src/cli/templates/provider/{skills → .agents/skills}/pagination-and-counts/SKILL.md.tpl
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|