@forgezero/providers 0.1.9 → 0.1.10
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 +160 -52
- package/dist/binance.js +95 -38
- package/dist/chain.d.ts +1 -1
- package/dist/chain.js +95 -38
- package/dist/database.d.ts +2 -2
- package/dist/database.js +95 -38
- package/dist/email.d.ts +26 -44
- package/dist/email.js +160 -127
- package/dist/http.d.ts +2 -2
- package/dist/http.js +95 -38
- package/dist/index.d.ts +80 -17
- package/dist/index.js +97 -36
- package/dist/pool.js +95 -38
- package/dist/storage.d.ts +2 -2
- package/dist/storage.js +95 -38
- package/dist/translation.d.ts +6 -4
- package/dist/translation.js +95 -38
- package/package.json +5 -5
package/dist/storage.js
CHANGED
|
@@ -38,25 +38,45 @@ function chainCredentials(...sources) {
|
|
|
38
38
|
}
|
|
39
39
|
};
|
|
40
40
|
}
|
|
41
|
-
function staticConfig(
|
|
41
|
+
function staticConfig(config) {
|
|
42
42
|
const health = new Map;
|
|
43
43
|
return {
|
|
44
44
|
name: "static",
|
|
45
|
-
async
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
45
|
+
async provider(instanceKey) {
|
|
46
|
+
const provider = config.providers[instanceKey];
|
|
47
|
+
return provider ? { instanceKey, ...provider, config: { ...provider.config } } : undefined;
|
|
48
|
+
},
|
|
49
|
+
async list(serviceKey, methodKey) {
|
|
50
|
+
return (config.services[serviceKey]?.[methodKey] ?? []).map((attachment) => ({
|
|
51
|
+
...attachment,
|
|
52
|
+
health: health.get(`${serviceKey}:${methodKey}:${attachment.instanceKey}:${attachment.providerMethod}`) ?? attachment.health
|
|
49
53
|
}));
|
|
50
54
|
},
|
|
51
|
-
async recordHealth(serviceKey,
|
|
52
|
-
health.set(`${serviceKey}:${
|
|
55
|
+
async recordHealth(serviceKey, methodKey, instanceKey, providerMethod, next) {
|
|
56
|
+
health.set(`${serviceKey}:${methodKey}:${instanceKey}:${providerMethod}`, next);
|
|
53
57
|
}
|
|
54
58
|
};
|
|
55
59
|
}
|
|
60
|
+
function defineProviderMethod(method) {
|
|
61
|
+
return method;
|
|
62
|
+
}
|
|
56
63
|
function defineProvider(spec) {
|
|
57
64
|
return spec;
|
|
58
65
|
}
|
|
66
|
+
function defineSingleMethodProvider(spec) {
|
|
67
|
+
const { method, invoke, classify, ...identity } = spec;
|
|
68
|
+
return defineProvider({
|
|
69
|
+
...identity,
|
|
70
|
+
methods: { [method]: defineProviderMethod({ invoke, classify }) }
|
|
71
|
+
});
|
|
72
|
+
}
|
|
59
73
|
var STRIKES_TO_OFFLINE = 3;
|
|
74
|
+
function serviceMethod() {
|
|
75
|
+
return Object.freeze({});
|
|
76
|
+
}
|
|
77
|
+
function defineService(definition) {
|
|
78
|
+
return definition;
|
|
79
|
+
}
|
|
60
80
|
function nextHealth(current, kind) {
|
|
61
81
|
if (kind === "success")
|
|
62
82
|
return { strikes: 0, status: "ok" };
|
|
@@ -71,80 +91,117 @@ function nextHealth(current, kind) {
|
|
|
71
91
|
}
|
|
72
92
|
function createRegistry(options) {
|
|
73
93
|
const byId = new Map(options.providers.map((provider) => [provider.id, provider]));
|
|
74
|
-
async function call(serviceKey, args, callOptions = {}) {
|
|
75
|
-
const configured = [...await options.config.list(serviceKey)].filter((
|
|
94
|
+
async function call(serviceKey, methodKey, args, callOptions = {}) {
|
|
95
|
+
const configured = [...await options.config.list(serviceKey, methodKey)].filter((attachment) => attachment.enabled).sort((a, b) => a.priority - b.priority);
|
|
76
96
|
const attempts = [];
|
|
77
|
-
for (const
|
|
97
|
+
for (const attachment of configured) {
|
|
78
98
|
if (callOptions.signal?.aborted) {
|
|
79
99
|
const cancelled = {
|
|
80
100
|
ok: false,
|
|
101
|
+
fallbackUsed: attempts.length > 0,
|
|
81
102
|
attempts,
|
|
82
|
-
error: new ProviderError("CALL_ABORTED", `The "${serviceKey}" call was cancelled.`)
|
|
103
|
+
error: new ProviderError("CALL_ABORTED", `The "${serviceKey}.${methodKey}" call was cancelled.`)
|
|
83
104
|
};
|
|
84
|
-
options.after?.(cancelled);
|
|
105
|
+
await options.after?.(cancelled);
|
|
85
106
|
return cancelled;
|
|
86
107
|
}
|
|
87
|
-
const
|
|
88
|
-
if (!
|
|
89
|
-
attempts.push({ providerId:
|
|
108
|
+
const instance = await options.config.provider(attachment.instanceKey);
|
|
109
|
+
if (!instance) {
|
|
110
|
+
attempts.push({ providerId: "unknown", instanceKey: attachment.instanceKey, providerMethod: attachment.providerMethod, outcome: "skipped", error: "instance not registered" });
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
const spec = byId.get(instance.providerId);
|
|
114
|
+
const method = spec?.methods[attachment.providerMethod];
|
|
115
|
+
if (!spec || !method) {
|
|
116
|
+
attempts.push({ providerId: instance.providerId, instanceKey: instance.instanceKey, providerMethod: attachment.providerMethod, outcome: "skipped", error: !spec ? "provider not registered" : "method not supported" });
|
|
90
117
|
continue;
|
|
91
118
|
}
|
|
92
|
-
if (
|
|
93
|
-
attempts.push({ providerId:
|
|
119
|
+
if (!instance.enabled) {
|
|
120
|
+
attempts.push({ providerId: instance.providerId, instanceKey: instance.instanceKey, providerMethod: attachment.providerMethod, outcome: "skipped", error: "instance disabled" });
|
|
94
121
|
continue;
|
|
95
122
|
}
|
|
96
|
-
|
|
123
|
+
if (attachment.health?.status === "offline") {
|
|
124
|
+
attempts.push({ providerId: instance.providerId, instanceKey: instance.instanceKey, providerMethod: attachment.providerMethod, outcome: "skipped", error: "offline" });
|
|
125
|
+
continue;
|
|
126
|
+
}
|
|
127
|
+
await options.before?.({ service: serviceKey, method: methodKey, provider: instance.providerId, instance: instance.instanceKey });
|
|
128
|
+
const startedAt = performance.now();
|
|
97
129
|
try {
|
|
98
|
-
const result = await
|
|
99
|
-
config:
|
|
100
|
-
secret: (field) => options.credentials.get(
|
|
130
|
+
const result = await method.invoke({
|
|
131
|
+
config: instance.config,
|
|
132
|
+
secret: (field) => options.credentials.get(instance.secretRef, field),
|
|
101
133
|
signal: callOptions.signal
|
|
102
134
|
}, args);
|
|
103
|
-
attempts.push({ providerId:
|
|
104
|
-
await options.config.recordHealth(serviceKey,
|
|
105
|
-
const sent = {
|
|
106
|
-
|
|
135
|
+
attempts.push({ providerId: instance.providerId, instanceKey: instance.instanceKey, providerMethod: attachment.providerMethod, outcome: "sent", durationMs: performance.now() - startedAt });
|
|
136
|
+
await options.config.recordHealth(serviceKey, methodKey, instance.instanceKey, attachment.providerMethod, nextHealth(attachment.health, "success"));
|
|
137
|
+
const sent = {
|
|
138
|
+
ok: true,
|
|
139
|
+
result,
|
|
140
|
+
provider: instance.providerId,
|
|
141
|
+
instance: instance.instanceKey,
|
|
142
|
+
method: attachment.providerMethod,
|
|
143
|
+
selected: { providerId: instance.providerId, instanceKey: instance.instanceKey, providerMethod: attachment.providerMethod },
|
|
144
|
+
fallbackUsed: attempts.length > 1,
|
|
145
|
+
attempts
|
|
146
|
+
};
|
|
147
|
+
await options.after?.(sent);
|
|
107
148
|
return sent;
|
|
108
149
|
} catch (error) {
|
|
109
150
|
if (callOptions.signal?.aborted) {
|
|
110
151
|
const cancelled = {
|
|
111
152
|
ok: false,
|
|
153
|
+
fallbackUsed: attempts.length > 0,
|
|
112
154
|
attempts,
|
|
113
|
-
error: new ProviderError("CALL_ABORTED", `The "${serviceKey}" call was cancelled.`)
|
|
155
|
+
error: new ProviderError("CALL_ABORTED", `The "${serviceKey}.${methodKey}" call was cancelled.`)
|
|
114
156
|
};
|
|
115
|
-
options.after?.(cancelled);
|
|
157
|
+
await options.after?.(cancelled);
|
|
116
158
|
return cancelled;
|
|
117
159
|
}
|
|
118
|
-
const kind =
|
|
160
|
+
const kind = method.classify(error);
|
|
161
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
162
|
+
const code = error instanceof ProviderError ? error.code : typeof error?.code === "string" ? error.code : undefined;
|
|
119
163
|
attempts.push({
|
|
120
|
-
providerId:
|
|
164
|
+
providerId: instance.providerId,
|
|
165
|
+
instanceKey: instance.instanceKey,
|
|
166
|
+
providerMethod: attachment.providerMethod,
|
|
121
167
|
outcome: "failed",
|
|
122
168
|
kind,
|
|
123
|
-
|
|
169
|
+
durationMs: performance.now() - startedAt,
|
|
170
|
+
failure: { kind, ...code ? { code } : {}, message },
|
|
171
|
+
error: message
|
|
124
172
|
});
|
|
125
|
-
await options.config.recordHealth(serviceKey,
|
|
173
|
+
await options.config.recordHealth(serviceKey, methodKey, instance.instanceKey, attachment.providerMethod, nextHealth(attachment.health, kind));
|
|
126
174
|
if (kind === "terminal") {
|
|
127
175
|
const refused = {
|
|
128
176
|
ok: false,
|
|
177
|
+
fallbackUsed: attempts.length > 1,
|
|
129
178
|
attempts,
|
|
130
179
|
error: new ProviderError("PAYLOAD_REJECTED", "The request was refused as malformed; no provider will accept it.")
|
|
131
180
|
};
|
|
132
|
-
options.after?.(refused);
|
|
181
|
+
await options.after?.(refused);
|
|
133
182
|
return refused;
|
|
134
183
|
}
|
|
135
184
|
}
|
|
136
185
|
}
|
|
137
186
|
const failed = {
|
|
138
187
|
ok: false,
|
|
188
|
+
fallbackUsed: attempts.length > 1,
|
|
139
189
|
attempts,
|
|
140
|
-
error: new ProviderError(attempts.length === 0 ? "NO_PROVIDER" : "ALL_PROVIDERS_FAILED", attempts.length === 0 ? `No provider is configured for "${serviceKey}".` : `Every provider for "${serviceKey}" failed or was skipped.`)
|
|
190
|
+
error: new ProviderError(attempts.length === 0 ? "NO_PROVIDER" : "ALL_PROVIDERS_FAILED", attempts.length === 0 ? `No provider method is configured for "${serviceKey}.${methodKey}".` : `Every provider method for "${serviceKey}.${methodKey}" failed or was skipped.`)
|
|
141
191
|
};
|
|
142
|
-
options.after?.(failed);
|
|
192
|
+
await options.after?.(failed);
|
|
143
193
|
return failed;
|
|
144
194
|
}
|
|
145
|
-
|
|
195
|
+
function service(definition) {
|
|
196
|
+
return {
|
|
197
|
+
call(method, args, callOptions) {
|
|
198
|
+
return call(definition.key, method, args, callOptions);
|
|
199
|
+
}
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
return { call, service };
|
|
146
203
|
}
|
|
147
|
-
var VERSION = "0.1.
|
|
204
|
+
var VERSION = "0.1.10";
|
|
148
205
|
|
|
149
206
|
// src/storage.ts
|
|
150
207
|
var encoder = new TextEncoder;
|
|
@@ -381,9 +438,9 @@ var extractS3Message = (xml) => {
|
|
|
381
438
|
const message = between(xml, "<Message>", "</Message>");
|
|
382
439
|
return code || message ? `${code ?? ""}${code && message ? ": " : ""}${message ?? ""}` : undefined;
|
|
383
440
|
};
|
|
384
|
-
var s3 =
|
|
441
|
+
var s3 = defineSingleMethodProvider({
|
|
385
442
|
id: "s3",
|
|
386
|
-
|
|
443
|
+
method: "request",
|
|
387
444
|
label: "S3-compatible storage",
|
|
388
445
|
multiInstance: true,
|
|
389
446
|
credentials: {
|
package/dist/translation.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { type ProviderDefinition, type ProviderMethodSpec } from './index';
|
|
2
2
|
/**
|
|
3
3
|
* Machine translation, as a service with providers behind it.
|
|
4
4
|
*
|
|
@@ -41,7 +41,9 @@ export interface TranslateResult {
|
|
|
41
41
|
model?: string;
|
|
42
42
|
}
|
|
43
43
|
/** Anything that can translate. A tenant may supply their own. */
|
|
44
|
-
export type TranslationProvider =
|
|
44
|
+
export type TranslationProvider = ProviderDefinition<{
|
|
45
|
+
translate: ProviderMethodSpec<TranslateRequest, TranslateResult>;
|
|
46
|
+
}>;
|
|
45
47
|
/**
|
|
46
48
|
* Google AI Studio, on the free tier.
|
|
47
49
|
*
|
|
@@ -53,7 +55,7 @@ export type TranslationProvider = ReturnType<typeof defineProvider<TranslateRequ
|
|
|
53
55
|
* and parsing whatever comes back is how translation pipelines start returning
|
|
54
56
|
* markdown fences on a Tuesday; a schema makes the shape the model's problem.
|
|
55
57
|
*/
|
|
56
|
-
export declare const googleAiStudio:
|
|
58
|
+
export declare const googleAiStudio: ProviderDefinition<Record<"translate", ProviderMethodSpec<TranslateRequest, TranslateResult>>>;
|
|
57
59
|
export declare class TranslationError extends Error {
|
|
58
60
|
readonly code: 'NO_CREDENTIAL' | 'RATE_LIMITED' | 'REQUEST_FAILED' | 'EMPTY_RESPONSE' | 'LENGTH_MISMATCH';
|
|
59
61
|
readonly status?: number | undefined;
|
|
@@ -67,4 +69,4 @@ export declare class TranslationError extends Error {
|
|
|
67
69
|
* both costs three lines and removes a class of "worked until we changed model".
|
|
68
70
|
*/
|
|
69
71
|
export declare function parseStrings(raw: string): string[];
|
|
70
|
-
export declare const translationProviders: readonly [
|
|
72
|
+
export declare const translationProviders: readonly [ProviderDefinition<Record<"translate", ProviderMethodSpec<TranslateRequest, TranslateResult>>>];
|
package/dist/translation.js
CHANGED
|
@@ -38,25 +38,45 @@ function chainCredentials(...sources) {
|
|
|
38
38
|
}
|
|
39
39
|
};
|
|
40
40
|
}
|
|
41
|
-
function staticConfig(
|
|
41
|
+
function staticConfig(config) {
|
|
42
42
|
const health = new Map;
|
|
43
43
|
return {
|
|
44
44
|
name: "static",
|
|
45
|
-
async
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
45
|
+
async provider(instanceKey) {
|
|
46
|
+
const provider = config.providers[instanceKey];
|
|
47
|
+
return provider ? { instanceKey, ...provider, config: { ...provider.config } } : undefined;
|
|
48
|
+
},
|
|
49
|
+
async list(serviceKey, methodKey) {
|
|
50
|
+
return (config.services[serviceKey]?.[methodKey] ?? []).map((attachment) => ({
|
|
51
|
+
...attachment,
|
|
52
|
+
health: health.get(`${serviceKey}:${methodKey}:${attachment.instanceKey}:${attachment.providerMethod}`) ?? attachment.health
|
|
49
53
|
}));
|
|
50
54
|
},
|
|
51
|
-
async recordHealth(serviceKey,
|
|
52
|
-
health.set(`${serviceKey}:${
|
|
55
|
+
async recordHealth(serviceKey, methodKey, instanceKey, providerMethod, next) {
|
|
56
|
+
health.set(`${serviceKey}:${methodKey}:${instanceKey}:${providerMethod}`, next);
|
|
53
57
|
}
|
|
54
58
|
};
|
|
55
59
|
}
|
|
60
|
+
function defineProviderMethod(method) {
|
|
61
|
+
return method;
|
|
62
|
+
}
|
|
56
63
|
function defineProvider(spec) {
|
|
57
64
|
return spec;
|
|
58
65
|
}
|
|
66
|
+
function defineSingleMethodProvider(spec) {
|
|
67
|
+
const { method, invoke, classify, ...identity } = spec;
|
|
68
|
+
return defineProvider({
|
|
69
|
+
...identity,
|
|
70
|
+
methods: { [method]: defineProviderMethod({ invoke, classify }) }
|
|
71
|
+
});
|
|
72
|
+
}
|
|
59
73
|
var STRIKES_TO_OFFLINE = 3;
|
|
74
|
+
function serviceMethod() {
|
|
75
|
+
return Object.freeze({});
|
|
76
|
+
}
|
|
77
|
+
function defineService(definition) {
|
|
78
|
+
return definition;
|
|
79
|
+
}
|
|
60
80
|
function nextHealth(current, kind) {
|
|
61
81
|
if (kind === "success")
|
|
62
82
|
return { strikes: 0, status: "ok" };
|
|
@@ -71,86 +91,123 @@ function nextHealth(current, kind) {
|
|
|
71
91
|
}
|
|
72
92
|
function createRegistry(options) {
|
|
73
93
|
const byId = new Map(options.providers.map((provider) => [provider.id, provider]));
|
|
74
|
-
async function call(serviceKey, args, callOptions = {}) {
|
|
75
|
-
const configured = [...await options.config.list(serviceKey)].filter((
|
|
94
|
+
async function call(serviceKey, methodKey, args, callOptions = {}) {
|
|
95
|
+
const configured = [...await options.config.list(serviceKey, methodKey)].filter((attachment) => attachment.enabled).sort((a, b) => a.priority - b.priority);
|
|
76
96
|
const attempts = [];
|
|
77
|
-
for (const
|
|
97
|
+
for (const attachment of configured) {
|
|
78
98
|
if (callOptions.signal?.aborted) {
|
|
79
99
|
const cancelled = {
|
|
80
100
|
ok: false,
|
|
101
|
+
fallbackUsed: attempts.length > 0,
|
|
81
102
|
attempts,
|
|
82
|
-
error: new ProviderError("CALL_ABORTED", `The "${serviceKey}" call was cancelled.`)
|
|
103
|
+
error: new ProviderError("CALL_ABORTED", `The "${serviceKey}.${methodKey}" call was cancelled.`)
|
|
83
104
|
};
|
|
84
|
-
options.after?.(cancelled);
|
|
105
|
+
await options.after?.(cancelled);
|
|
85
106
|
return cancelled;
|
|
86
107
|
}
|
|
87
|
-
const
|
|
88
|
-
if (!
|
|
89
|
-
attempts.push({ providerId:
|
|
108
|
+
const instance = await options.config.provider(attachment.instanceKey);
|
|
109
|
+
if (!instance) {
|
|
110
|
+
attempts.push({ providerId: "unknown", instanceKey: attachment.instanceKey, providerMethod: attachment.providerMethod, outcome: "skipped", error: "instance not registered" });
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
const spec = byId.get(instance.providerId);
|
|
114
|
+
const method = spec?.methods[attachment.providerMethod];
|
|
115
|
+
if (!spec || !method) {
|
|
116
|
+
attempts.push({ providerId: instance.providerId, instanceKey: instance.instanceKey, providerMethod: attachment.providerMethod, outcome: "skipped", error: !spec ? "provider not registered" : "method not supported" });
|
|
90
117
|
continue;
|
|
91
118
|
}
|
|
92
|
-
if (
|
|
93
|
-
attempts.push({ providerId:
|
|
119
|
+
if (!instance.enabled) {
|
|
120
|
+
attempts.push({ providerId: instance.providerId, instanceKey: instance.instanceKey, providerMethod: attachment.providerMethod, outcome: "skipped", error: "instance disabled" });
|
|
94
121
|
continue;
|
|
95
122
|
}
|
|
96
|
-
|
|
123
|
+
if (attachment.health?.status === "offline") {
|
|
124
|
+
attempts.push({ providerId: instance.providerId, instanceKey: instance.instanceKey, providerMethod: attachment.providerMethod, outcome: "skipped", error: "offline" });
|
|
125
|
+
continue;
|
|
126
|
+
}
|
|
127
|
+
await options.before?.({ service: serviceKey, method: methodKey, provider: instance.providerId, instance: instance.instanceKey });
|
|
128
|
+
const startedAt = performance.now();
|
|
97
129
|
try {
|
|
98
|
-
const result = await
|
|
99
|
-
config:
|
|
100
|
-
secret: (field) => options.credentials.get(
|
|
130
|
+
const result = await method.invoke({
|
|
131
|
+
config: instance.config,
|
|
132
|
+
secret: (field) => options.credentials.get(instance.secretRef, field),
|
|
101
133
|
signal: callOptions.signal
|
|
102
134
|
}, args);
|
|
103
|
-
attempts.push({ providerId:
|
|
104
|
-
await options.config.recordHealth(serviceKey,
|
|
105
|
-
const sent = {
|
|
106
|
-
|
|
135
|
+
attempts.push({ providerId: instance.providerId, instanceKey: instance.instanceKey, providerMethod: attachment.providerMethod, outcome: "sent", durationMs: performance.now() - startedAt });
|
|
136
|
+
await options.config.recordHealth(serviceKey, methodKey, instance.instanceKey, attachment.providerMethod, nextHealth(attachment.health, "success"));
|
|
137
|
+
const sent = {
|
|
138
|
+
ok: true,
|
|
139
|
+
result,
|
|
140
|
+
provider: instance.providerId,
|
|
141
|
+
instance: instance.instanceKey,
|
|
142
|
+
method: attachment.providerMethod,
|
|
143
|
+
selected: { providerId: instance.providerId, instanceKey: instance.instanceKey, providerMethod: attachment.providerMethod },
|
|
144
|
+
fallbackUsed: attempts.length > 1,
|
|
145
|
+
attempts
|
|
146
|
+
};
|
|
147
|
+
await options.after?.(sent);
|
|
107
148
|
return sent;
|
|
108
149
|
} catch (error) {
|
|
109
150
|
if (callOptions.signal?.aborted) {
|
|
110
151
|
const cancelled = {
|
|
111
152
|
ok: false,
|
|
153
|
+
fallbackUsed: attempts.length > 0,
|
|
112
154
|
attempts,
|
|
113
|
-
error: new ProviderError("CALL_ABORTED", `The "${serviceKey}" call was cancelled.`)
|
|
155
|
+
error: new ProviderError("CALL_ABORTED", `The "${serviceKey}.${methodKey}" call was cancelled.`)
|
|
114
156
|
};
|
|
115
|
-
options.after?.(cancelled);
|
|
157
|
+
await options.after?.(cancelled);
|
|
116
158
|
return cancelled;
|
|
117
159
|
}
|
|
118
|
-
const kind =
|
|
160
|
+
const kind = method.classify(error);
|
|
161
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
162
|
+
const code = error instanceof ProviderError ? error.code : typeof error?.code === "string" ? error.code : undefined;
|
|
119
163
|
attempts.push({
|
|
120
|
-
providerId:
|
|
164
|
+
providerId: instance.providerId,
|
|
165
|
+
instanceKey: instance.instanceKey,
|
|
166
|
+
providerMethod: attachment.providerMethod,
|
|
121
167
|
outcome: "failed",
|
|
122
168
|
kind,
|
|
123
|
-
|
|
169
|
+
durationMs: performance.now() - startedAt,
|
|
170
|
+
failure: { kind, ...code ? { code } : {}, message },
|
|
171
|
+
error: message
|
|
124
172
|
});
|
|
125
|
-
await options.config.recordHealth(serviceKey,
|
|
173
|
+
await options.config.recordHealth(serviceKey, methodKey, instance.instanceKey, attachment.providerMethod, nextHealth(attachment.health, kind));
|
|
126
174
|
if (kind === "terminal") {
|
|
127
175
|
const refused = {
|
|
128
176
|
ok: false,
|
|
177
|
+
fallbackUsed: attempts.length > 1,
|
|
129
178
|
attempts,
|
|
130
179
|
error: new ProviderError("PAYLOAD_REJECTED", "The request was refused as malformed; no provider will accept it.")
|
|
131
180
|
};
|
|
132
|
-
options.after?.(refused);
|
|
181
|
+
await options.after?.(refused);
|
|
133
182
|
return refused;
|
|
134
183
|
}
|
|
135
184
|
}
|
|
136
185
|
}
|
|
137
186
|
const failed = {
|
|
138
187
|
ok: false,
|
|
188
|
+
fallbackUsed: attempts.length > 1,
|
|
139
189
|
attempts,
|
|
140
|
-
error: new ProviderError(attempts.length === 0 ? "NO_PROVIDER" : "ALL_PROVIDERS_FAILED", attempts.length === 0 ? `No provider is configured for "${serviceKey}".` : `Every provider for "${serviceKey}" failed or was skipped.`)
|
|
190
|
+
error: new ProviderError(attempts.length === 0 ? "NO_PROVIDER" : "ALL_PROVIDERS_FAILED", attempts.length === 0 ? `No provider method is configured for "${serviceKey}.${methodKey}".` : `Every provider method for "${serviceKey}.${methodKey}" failed or was skipped.`)
|
|
141
191
|
};
|
|
142
|
-
options.after?.(failed);
|
|
192
|
+
await options.after?.(failed);
|
|
143
193
|
return failed;
|
|
144
194
|
}
|
|
145
|
-
|
|
195
|
+
function service(definition) {
|
|
196
|
+
return {
|
|
197
|
+
call(method, args, callOptions) {
|
|
198
|
+
return call(definition.key, method, args, callOptions);
|
|
199
|
+
}
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
return { call, service };
|
|
146
203
|
}
|
|
147
|
-
var VERSION = "0.1.
|
|
204
|
+
var VERSION = "0.1.10";
|
|
148
205
|
|
|
149
206
|
// src/translation.ts
|
|
150
207
|
var GOOGLE_ENDPOINT = "https://generativelanguage.googleapis.com/v1beta/models";
|
|
151
|
-
var googleAiStudio =
|
|
208
|
+
var googleAiStudio = defineSingleMethodProvider({
|
|
152
209
|
id: "google-ai-studio",
|
|
153
|
-
|
|
210
|
+
method: "translate",
|
|
154
211
|
label: "Google AI Studio",
|
|
155
212
|
credentials: {
|
|
156
213
|
type: "object",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@forgezero/providers",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.10",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public",
|
|
@@ -42,12 +42,12 @@
|
|
|
42
42
|
"./translation": {
|
|
43
43
|
"types": "./dist/translation.d.ts",
|
|
44
44
|
"default": "./dist/translation.js"
|
|
45
|
-
|
|
46
|
-
},
|
|
45
|
+
},
|
|
47
46
|
"./realtime": {
|
|
48
47
|
"types": "./dist/realtime.d.ts",
|
|
49
48
|
"default": "./dist/realtime.js"
|
|
50
|
-
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
51
|
"scripts": {
|
|
52
52
|
"check": "tsc --noEmit",
|
|
53
53
|
"prebuild": "rm -rf dist",
|
|
@@ -86,6 +86,6 @@
|
|
|
86
86
|
"LICENSE"
|
|
87
87
|
],
|
|
88
88
|
"dependencies": {
|
|
89
|
-
|
|
89
|
+
"@forgezero/runtime": "^0.1.6"
|
|
90
90
|
}
|
|
91
91
|
}
|