praxis-agent 0.53.1 → 0.55.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +29 -5
- package/dist/application/native-sidechain-transcript.d.ts +2 -0
- package/dist/application/native-sidechain-transcript.js +3 -0
- package/dist/application/session-service.d.ts +2 -0
- package/dist/application/session-service.js +22 -1
- package/dist/application/subagent-service.d.ts +2 -0
- package/dist/application/subagent-service.js +28 -12
- package/dist/application/team-agent-runtime.d.ts +1 -0
- package/dist/application/team-agent-runtime.js +3 -0
- package/dist/cli-runtime.js +19 -6
- package/dist/providers/codex-subscription.d.ts +1 -7
- package/dist/providers/codex-subscription.js +32 -694
- package/dist/providers/fallback-provider.d.ts +5 -1
- package/dist/providers/fallback-provider.js +62 -4
- package/dist/providers/openai-responses.d.ts +26 -0
- package/dist/providers/openai-responses.js +162 -0
- package/dist/providers/provider-registry.js +22 -0
- package/dist/providers/provider-settings.d.ts +1 -1
- package/dist/providers/provider-settings.js +13 -2
- package/dist/providers/responses-codec.d.ts +31 -0
- package/dist/providers/responses-codec.js +742 -0
- package/package.json +1 -1
|
@@ -2,12 +2,16 @@ import { type ModelProvider, type ModelStreamEvent, type ModelRequest } from '..
|
|
|
2
2
|
export interface FallbackModelProviderOptions {
|
|
3
3
|
providers: readonly ModelProvider[];
|
|
4
4
|
retryDelayMs?: number;
|
|
5
|
+
routeScope?: 'completion' | 'turn';
|
|
5
6
|
}
|
|
6
7
|
/** Routes each complete request through Claude's retry-then-fallback policy. */
|
|
7
8
|
export declare class FallbackModelProvider implements ModelProvider {
|
|
8
9
|
private active;
|
|
9
10
|
private readonly retryDelayMs;
|
|
10
|
-
private readonly
|
|
11
|
+
private readonly configuredProviders;
|
|
12
|
+
private readonly routeScope;
|
|
13
|
+
private currentProviderIndex;
|
|
14
|
+
private routeSealed;
|
|
11
15
|
constructor(options: FallbackModelProviderOptions);
|
|
12
16
|
/** Capabilities of the currently active provider after any fallback routing. */
|
|
13
17
|
get capabilities(): ModelProvider['capabilities'];
|
|
@@ -42,14 +42,18 @@ async function waitForRetry(delayMs, signal) {
|
|
|
42
42
|
export class FallbackModelProvider {
|
|
43
43
|
active;
|
|
44
44
|
retryDelayMs;
|
|
45
|
-
|
|
45
|
+
configuredProviders;
|
|
46
|
+
routeScope;
|
|
47
|
+
currentProviderIndex = 0;
|
|
48
|
+
routeSealed = false;
|
|
46
49
|
constructor(options) {
|
|
47
50
|
if (options.providers.length === 0) {
|
|
48
51
|
throw new Error('Fallback provider requires at least one provider');
|
|
49
52
|
}
|
|
50
53
|
this.active = options.providers[0];
|
|
51
|
-
this.
|
|
54
|
+
this.configuredProviders = options.providers;
|
|
52
55
|
this.retryDelayMs = options.retryDelayMs ?? 500;
|
|
56
|
+
this.routeScope = options.routeScope ?? 'turn';
|
|
53
57
|
}
|
|
54
58
|
/** Capabilities of the currently active provider after any fallback routing. */
|
|
55
59
|
get capabilities() {
|
|
@@ -60,9 +64,12 @@ export class FallbackModelProvider {
|
|
|
60
64
|
}
|
|
61
65
|
async *complete(request) {
|
|
62
66
|
let lastError;
|
|
63
|
-
for (const provider of this.providers()) {
|
|
67
|
+
for (const [providerIndex, provider] of this.providers()) {
|
|
68
|
+
if (providerIndex > 0)
|
|
69
|
+
validateCapabilities(provider, request);
|
|
64
70
|
for (let attempt = 0; attempt < MAX_ATTEMPTS_PER_MODEL; attempt += 1) {
|
|
65
71
|
throwIfAborted(request.signal);
|
|
72
|
+
this.currentProviderIndex = providerIndex;
|
|
66
73
|
this.active = provider;
|
|
67
74
|
const attemptStartedAt = performance.now();
|
|
68
75
|
try {
|
|
@@ -97,6 +104,9 @@ export class FallbackModelProvider {
|
|
|
97
104
|
if (provider.capabilities.terminalReasons === true && !terminalSeen) {
|
|
98
105
|
throw new ModelProviderError('Provider stream ended without a terminal reason', { retryable: true });
|
|
99
106
|
}
|
|
107
|
+
this.currentProviderIndex = providerIndex;
|
|
108
|
+
this.active = provider;
|
|
109
|
+
this.routeSealed = this.routeScope === 'turn';
|
|
100
110
|
yield {
|
|
101
111
|
type: 'api-attempt-duration',
|
|
102
112
|
durationMs: attemptDurationMs ??
|
|
@@ -133,7 +143,55 @@ export class FallbackModelProvider {
|
|
|
133
143
|
: new Error(String(lastError ?? 'All model providers failed'));
|
|
134
144
|
}
|
|
135
145
|
providers() {
|
|
136
|
-
|
|
146
|
+
if (this.routeSealed) {
|
|
147
|
+
const provider = this.configuredProviders[this.currentProviderIndex];
|
|
148
|
+
return provider === undefined
|
|
149
|
+
? []
|
|
150
|
+
: [[this.currentProviderIndex, provider]];
|
|
151
|
+
}
|
|
152
|
+
return this.configuredProviders.map((provider, index) => [index, provider]);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
function validateCapabilities(provider, request) {
|
|
156
|
+
const capabilities = provider.capabilities;
|
|
157
|
+
if (!capabilities.streaming) {
|
|
158
|
+
throw capabilityError(provider, 'streaming');
|
|
159
|
+
}
|
|
160
|
+
if (request.tools !== undefined &&
|
|
161
|
+
request.tools.length > 0 &&
|
|
162
|
+
!capabilities.tools) {
|
|
163
|
+
throw capabilityError(provider, 'tools');
|
|
164
|
+
}
|
|
165
|
+
const hasImages = request.messages.some((message) => ('images' in message &&
|
|
166
|
+
message.images !== undefined &&
|
|
167
|
+
message.images.length > 0) ||
|
|
168
|
+
('contentBlocks' in message &&
|
|
169
|
+
message.contentBlocks?.some((block) => block.type === 'image') ===
|
|
170
|
+
true));
|
|
171
|
+
if (hasImages && !capabilities.images)
|
|
172
|
+
throw capabilityError(provider, 'images');
|
|
173
|
+
const hasDocuments = request.messages.some((message) => ('documents' in message &&
|
|
174
|
+
message.documents !== undefined &&
|
|
175
|
+
message.documents.length > 0) ||
|
|
176
|
+
('contentBlocks' in message &&
|
|
177
|
+
message.contentBlocks?.some((block) => block.type === 'document') ===
|
|
178
|
+
true));
|
|
179
|
+
if (hasDocuments && !capabilities.documents)
|
|
180
|
+
throw capabilityError(provider, 'documents');
|
|
181
|
+
if (request.webSearch !== undefined && !capabilities.webSearch) {
|
|
182
|
+
throw capabilityError(provider, 'webSearch');
|
|
137
183
|
}
|
|
184
|
+
const thinking = request.thinking;
|
|
185
|
+
if (thinking?.maxTokens !== undefined && !capabilities.thinking?.maxTokens) {
|
|
186
|
+
throw capabilityError(provider, 'thinking maxTokens');
|
|
187
|
+
}
|
|
188
|
+
if (thinking !== undefined) {
|
|
189
|
+
if (!capabilities.thinking?.modes.includes(thinking.mode)) {
|
|
190
|
+
throw capabilityError(provider, `thinking mode ${thinking.mode}`);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
function capabilityError(provider, capability) {
|
|
195
|
+
return new ModelProviderError(`Provider ${provider.model ?? 'unknown'} does not support ${capability}`, { kind: 'invalid_request', retryable: false });
|
|
138
196
|
}
|
|
139
197
|
//# sourceMappingURL=fallback-provider.js.map
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { type ModelProvider, type ModelRequest, type ModelStreamEvent, type ModelThinkingConfig } from '../core/runtime.js';
|
|
2
|
+
export interface OpenAIResponsesProviderOptions {
|
|
3
|
+
baseUrl: string;
|
|
4
|
+
apiKey: string;
|
|
5
|
+
model: string;
|
|
6
|
+
contextWindowTokens?: number;
|
|
7
|
+
thinking?: ModelThinkingConfig;
|
|
8
|
+
maxStreamBufferBytes?: number;
|
|
9
|
+
maxToolArgumentsBytes?: number;
|
|
10
|
+
maxToolCallsPerResponse?: number;
|
|
11
|
+
maxToolMetadataBytes?: number;
|
|
12
|
+
maxReasoningBytes?: number;
|
|
13
|
+
maxErrorBodyBytes?: number;
|
|
14
|
+
fetchImplementation?: typeof fetch;
|
|
15
|
+
}
|
|
16
|
+
export declare class OpenAIResponsesProvider implements ModelProvider {
|
|
17
|
+
private readonly options;
|
|
18
|
+
readonly model: string;
|
|
19
|
+
readonly capabilities: ModelProvider['capabilities'];
|
|
20
|
+
private readonly fetchImplementation;
|
|
21
|
+
private readonly codec;
|
|
22
|
+
private readonly maxErrorBodyBytes;
|
|
23
|
+
constructor(options: OpenAIResponsesProviderOptions);
|
|
24
|
+
complete(request: ModelRequest): AsyncIterable<ModelStreamEvent>;
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=openai-responses.d.ts.map
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import { ModelProviderError, } from '../core/runtime.js';
|
|
2
|
+
import { ResponsesCodec } from './responses-codec.js';
|
|
3
|
+
import { reportProviderTransportActivity } from './provider-transport-activity.js';
|
|
4
|
+
function error(kind, retryable, status) {
|
|
5
|
+
return new ModelProviderError(status === undefined
|
|
6
|
+
? 'OpenAI Responses provider request failed'
|
|
7
|
+
: `OpenAI Responses provider request failed with HTTP ${status}`, { kind, retryable, ...(status === undefined ? {} : { status }) });
|
|
8
|
+
}
|
|
9
|
+
function statusError(status) {
|
|
10
|
+
if (status === 401 || status === 403)
|
|
11
|
+
return error('authentication_failed', false, status);
|
|
12
|
+
if (status === 402)
|
|
13
|
+
return error('billing_error', false, status);
|
|
14
|
+
if (status === 408)
|
|
15
|
+
return error('timeout', true, status);
|
|
16
|
+
if (status === 429)
|
|
17
|
+
return error('rate_limit', true, status);
|
|
18
|
+
if (status === 529)
|
|
19
|
+
return error('overloaded', true, status);
|
|
20
|
+
if (status >= 500)
|
|
21
|
+
return error('server_error', true, status);
|
|
22
|
+
return error('invalid_request', false, status);
|
|
23
|
+
}
|
|
24
|
+
function classifyErrorBody(body, status) {
|
|
25
|
+
let value;
|
|
26
|
+
try {
|
|
27
|
+
value = JSON.parse(body);
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
return statusError(status);
|
|
31
|
+
}
|
|
32
|
+
const record = value && typeof value === 'object'
|
|
33
|
+
? value
|
|
34
|
+
: undefined;
|
|
35
|
+
const nested = record?.error && typeof record.error === 'object'
|
|
36
|
+
? record.error
|
|
37
|
+
: record;
|
|
38
|
+
const text = [nested?.type, nested?.code, nested?.message]
|
|
39
|
+
.filter((item) => typeof item === 'string')
|
|
40
|
+
.join(' ');
|
|
41
|
+
if (/context[_ -]?length|prompt[_ -]?too[_ -]?long|context.{0,40}(?:exceed|too long)/iu.test(text))
|
|
42
|
+
return error('prompt_too_long', false, status);
|
|
43
|
+
if (nested?.type === 'overloaded_error')
|
|
44
|
+
return error('overloaded', true, status);
|
|
45
|
+
return statusError(status);
|
|
46
|
+
}
|
|
47
|
+
async function readErrorBody(response, maxBytes, request) {
|
|
48
|
+
const reader = response.body?.getReader();
|
|
49
|
+
if (!reader)
|
|
50
|
+
return '';
|
|
51
|
+
const decoder = new TextDecoder();
|
|
52
|
+
let body = '';
|
|
53
|
+
let remaining = maxBytes;
|
|
54
|
+
let ended = false;
|
|
55
|
+
try {
|
|
56
|
+
while (remaining > 0) {
|
|
57
|
+
const next = await reader.read();
|
|
58
|
+
if (next.done) {
|
|
59
|
+
ended = true;
|
|
60
|
+
body += decoder.decode();
|
|
61
|
+
break;
|
|
62
|
+
}
|
|
63
|
+
if (next.value.byteLength > 0)
|
|
64
|
+
reportProviderTransportActivity(request, 'response-chunk');
|
|
65
|
+
const chunk = next.value.subarray(0, remaining);
|
|
66
|
+
body += decoder.decode(chunk, { stream: chunk.byteLength === remaining });
|
|
67
|
+
remaining -= chunk.byteLength;
|
|
68
|
+
if (chunk.byteLength < next.value.byteLength)
|
|
69
|
+
break;
|
|
70
|
+
}
|
|
71
|
+
return body;
|
|
72
|
+
}
|
|
73
|
+
finally {
|
|
74
|
+
if (!ended) {
|
|
75
|
+
try {
|
|
76
|
+
await reader.cancel();
|
|
77
|
+
}
|
|
78
|
+
catch {
|
|
79
|
+
/* preserve the redacted HTTP error */
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
reader.releaseLock();
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
export class OpenAIResponsesProvider {
|
|
86
|
+
options;
|
|
87
|
+
model;
|
|
88
|
+
capabilities;
|
|
89
|
+
fetchImplementation;
|
|
90
|
+
codec;
|
|
91
|
+
maxErrorBodyBytes;
|
|
92
|
+
constructor(options) {
|
|
93
|
+
this.options = options;
|
|
94
|
+
this.model = options.model;
|
|
95
|
+
this.fetchImplementation = options.fetchImplementation ?? fetch;
|
|
96
|
+
this.codec = new ResponsesCodec({
|
|
97
|
+
providerLabel: 'OpenAI Responses provider',
|
|
98
|
+
...options,
|
|
99
|
+
});
|
|
100
|
+
this.maxErrorBodyBytes = options.maxErrorBodyBytes ?? 64 * 1024;
|
|
101
|
+
if (!Number.isSafeInteger(this.maxErrorBodyBytes) ||
|
|
102
|
+
this.maxErrorBodyBytes <= 0)
|
|
103
|
+
throw new Error('OpenAI Responses provider limits must be positive integers');
|
|
104
|
+
this.capabilities = {
|
|
105
|
+
streaming: true,
|
|
106
|
+
usage: true,
|
|
107
|
+
tools: true,
|
|
108
|
+
images: true,
|
|
109
|
+
documents: false,
|
|
110
|
+
webSearch: false,
|
|
111
|
+
thinking: {
|
|
112
|
+
modes: ['disabled', 'enabled', 'adaptive'],
|
|
113
|
+
maxTokens: false,
|
|
114
|
+
},
|
|
115
|
+
...(options.contextWindowTokens === undefined
|
|
116
|
+
? {}
|
|
117
|
+
: { contextWindowTokens: options.contextWindowTokens }),
|
|
118
|
+
terminalReasons: true,
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
async *complete(request) {
|
|
122
|
+
const body = this.codec.serialize(request, this.model);
|
|
123
|
+
const signal = request.signal;
|
|
124
|
+
let response;
|
|
125
|
+
try {
|
|
126
|
+
reportProviderTransportActivity(request, 'request-started');
|
|
127
|
+
response = await this.fetchImplementation(`${this.options.baseUrl.replace(/\/+$/u, '')}/responses`, {
|
|
128
|
+
method: 'POST',
|
|
129
|
+
headers: {
|
|
130
|
+
Authorization: `Bearer ${this.options.apiKey}`,
|
|
131
|
+
accept: 'text/event-stream',
|
|
132
|
+
'content-type': 'application/json',
|
|
133
|
+
},
|
|
134
|
+
body: JSON.stringify(body),
|
|
135
|
+
...(signal ? { signal } : {}),
|
|
136
|
+
});
|
|
137
|
+
reportProviderTransportActivity(request, 'response-received');
|
|
138
|
+
}
|
|
139
|
+
catch {
|
|
140
|
+
if (signal?.aborted)
|
|
141
|
+
throw error('cancelled', false);
|
|
142
|
+
throw error('transport_error', true);
|
|
143
|
+
}
|
|
144
|
+
if (!response.ok) {
|
|
145
|
+
let body = '';
|
|
146
|
+
try {
|
|
147
|
+
body = await readErrorBody(response, this.maxErrorBodyBytes, request);
|
|
148
|
+
}
|
|
149
|
+
catch {
|
|
150
|
+
/* preserve the redacted status classification */
|
|
151
|
+
}
|
|
152
|
+
throw classifyErrorBody(body, response.status);
|
|
153
|
+
}
|
|
154
|
+
if (!response.body)
|
|
155
|
+
throw error('transport_error', true);
|
|
156
|
+
yield* this.codec.stream(response.body, {
|
|
157
|
+
...(signal === undefined ? {} : { signal }),
|
|
158
|
+
onChunk: () => reportProviderTransportActivity(request, 'response-chunk'),
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
//# sourceMappingURL=openai-responses.js.map
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { AnthropicCompatibleProvider } from './anthropic-compatible.js';
|
|
2
2
|
import { OpenAICompatibleProvider } from './openai-compatible.js';
|
|
3
|
+
import { OpenAIResponsesProvider } from './openai-responses.js';
|
|
3
4
|
import { CodexSubscriptionProvider } from './codex-subscription.js';
|
|
4
5
|
import { DeadlineModelProvider } from './deadline-provider.js';
|
|
5
6
|
import { NonStreamingFallbackModelProvider } from './non-streaming-fallback-provider.js';
|
|
@@ -132,6 +133,27 @@ class NativeProviderRegistry {
|
|
|
132
133
|
: { fetchImplementation: this.options.fetchImplementation }),
|
|
133
134
|
}));
|
|
134
135
|
}
|
|
136
|
+
if (target.protocol === 'openai-responses') {
|
|
137
|
+
if (this.options.credential.type !== 'api-key') {
|
|
138
|
+
throw new ProviderAuthenticationError('invalid_credential', 'Provider authentication failed: an API key is required');
|
|
139
|
+
}
|
|
140
|
+
return this.withDeadline(new OpenAIResponsesProvider({
|
|
141
|
+
baseUrl: target.baseUrl,
|
|
142
|
+
model: target.modelId,
|
|
143
|
+
apiKey: this.options.credential.secret,
|
|
144
|
+
...(this.options.context?.contextWindowTokens === undefined
|
|
145
|
+
? {}
|
|
146
|
+
: {
|
|
147
|
+
contextWindowTokens: this.options.context.contextWindowTokens,
|
|
148
|
+
}),
|
|
149
|
+
...(this.options.openAiThinking === undefined
|
|
150
|
+
? {}
|
|
151
|
+
: { thinking: this.options.openAiThinking }),
|
|
152
|
+
...(this.options.fetchImplementation === undefined
|
|
153
|
+
? {}
|
|
154
|
+
: { fetchImplementation: this.options.fetchImplementation }),
|
|
155
|
+
}));
|
|
156
|
+
}
|
|
135
157
|
if (target.protocol === 'anthropic-messages') {
|
|
136
158
|
if (this.options.credential.type !== 'api-key') {
|
|
137
159
|
throw new ProviderAuthenticationError('invalid_credential', 'Provider authentication failed: an API key is required');
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type ProviderProtocol = 'openai-compatible' | 'anthropic-messages' | 'codex-subscription';
|
|
1
|
+
export type ProviderProtocol = 'openai-compatible' | 'openai-responses' | 'anthropic-messages' | 'codex-subscription';
|
|
2
2
|
export type CredentialSource = {
|
|
3
3
|
source: 'env';
|
|
4
4
|
name: string;
|
|
@@ -18,6 +18,15 @@ const BUILT_INS = {
|
|
|
18
18
|
},
|
|
19
19
|
},
|
|
20
20
|
},
|
|
21
|
+
'openai-responses': {
|
|
22
|
+
protocol: 'openai-responses',
|
|
23
|
+
profiles: {
|
|
24
|
+
default: {
|
|
25
|
+
baseUrl: 'https://api.openai.com/v1',
|
|
26
|
+
credential: { source: 'env', name: 'OPENAI_API_KEY' },
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
},
|
|
21
30
|
anthropic: {
|
|
22
31
|
protocol: 'anthropic-messages',
|
|
23
32
|
profiles: {
|
|
@@ -148,8 +157,10 @@ function parseProvider(value, providerId) {
|
|
|
148
157
|
'profiles',
|
|
149
158
|
]);
|
|
150
159
|
const protocol = value.protocol;
|
|
151
|
-
if (protocol !== 'openai-compatible' &&
|
|
152
|
-
|
|
160
|
+
if (protocol !== 'openai-compatible' &&
|
|
161
|
+
protocol !== 'openai-responses' &&
|
|
162
|
+
protocol !== 'anthropic-messages') {
|
|
163
|
+
fail(`providers.${providerId}.protocol must be openai-compatible, openai-responses, or anthropic-messages`);
|
|
153
164
|
}
|
|
154
165
|
if (!isRecord(value.profiles) || Object.keys(value.profiles).length === 0)
|
|
155
166
|
fail(`providers.${providerId}.profiles must be a non-empty object`);
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { type ModelRequest, type ModelStreamEvent, type ModelThinkingConfig } from '../core/runtime.js';
|
|
2
|
+
export interface ResponsesCodecOptions {
|
|
3
|
+
providerLabel?: string;
|
|
4
|
+
thinking?: ModelThinkingConfig;
|
|
5
|
+
maxStreamBufferBytes?: number;
|
|
6
|
+
maxToolArgumentsBytes?: number;
|
|
7
|
+
maxToolCallsPerResponse?: number;
|
|
8
|
+
maxToolMetadataBytes?: number;
|
|
9
|
+
maxReasoningBytes?: number;
|
|
10
|
+
}
|
|
11
|
+
export interface ResponsesStreamOptions {
|
|
12
|
+
signal?: AbortSignal;
|
|
13
|
+
onChunk?: () => void;
|
|
14
|
+
}
|
|
15
|
+
export declare class ResponsesCodec {
|
|
16
|
+
readonly maxStreamBufferBytes: number;
|
|
17
|
+
readonly maxToolArgumentsBytes: number;
|
|
18
|
+
readonly maxToolCallsPerResponse: number;
|
|
19
|
+
readonly maxToolMetadataBytes: number;
|
|
20
|
+
readonly maxReasoningBytes: number;
|
|
21
|
+
private readonly label;
|
|
22
|
+
private readonly configuredThinking;
|
|
23
|
+
constructor(options?: ResponsesCodecOptions);
|
|
24
|
+
serialize(request: ModelRequest, model: string): Record<string, unknown>;
|
|
25
|
+
stream(body: ReadableStream<Uint8Array>, options?: ResponsesStreamOptions): AsyncIterable<ModelStreamEvent>;
|
|
26
|
+
private createParser;
|
|
27
|
+
private parseFrame;
|
|
28
|
+
private contextualize;
|
|
29
|
+
private failure;
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=responses-codec.d.ts.map
|