@elizaos/plugin-elizacloud 2.0.0-beta.1 → 2.0.11-beta.7
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 +20 -44
- package/auto-enable.ts +10 -5
- package/dist/browser/index.browser.js +2 -2
- package/dist/browser/index.browser.js.map +4 -4
- package/dist/cjs/index.node.cjs +2874 -5915
- package/dist/cjs/index.node.js.map +47 -116
- package/dist/cloud/auth-service-types.d.ts +8 -0
- package/dist/cloud/auth-service-types.d.ts.map +1 -0
- package/dist/cloud/auth-service-types.js +36 -0
- package/dist/cloud/auth-service-types.js.map +10 -0
- package/dist/cloud/auth.js +4 -51
- package/dist/cloud/auth.js.map +4 -4
- package/dist/cloud/base-url.d.ts +6 -2
- package/dist/cloud/base-url.d.ts.map +1 -1
- package/dist/cloud/base-url.js +3 -51
- package/dist/cloud/base-url.js.map +3 -3
- package/dist/cloud/bridge-client.d.ts +3 -3
- package/dist/cloud/bridge-client.d.ts.map +1 -1
- package/dist/cloud/bridge-client.js +3 -51
- package/dist/cloud/bridge-client.js.map +3 -3
- package/dist/cloud/clack-observer.d.ts +35 -0
- package/dist/cloud/clack-observer.d.ts.map +1 -0
- package/dist/cloud/clack-observer.js +143 -0
- package/dist/cloud/clack-observer.js.map +10 -0
- package/dist/cloud/cloud-manager.js +45 -92
- package/dist/cloud/cloud-manager.js.map +6 -6
- package/dist/cloud/cloud-wallet.js +2 -4835
- package/dist/cloud/cloud-wallet.js.map +3 -82
- package/dist/cloud/duffel-client.d.ts +181 -0
- package/dist/cloud/duffel-client.d.ts.map +1 -0
- package/dist/cloud/duffel-client.js +506 -0
- package/dist/cloud/duffel-client.js.map +11 -0
- package/dist/cloud/index.d.ts +6 -0
- package/dist/cloud/index.d.ts.map +1 -1
- package/dist/cloud/index.js +1782 -1
- package/dist/cloud/index.js.map +18 -3
- package/dist/cloud/lifeops-schedule-sync-client.d.ts +43 -0
- package/dist/cloud/lifeops-schedule-sync-client.d.ts.map +1 -0
- package/dist/cloud/lifeops-schedule-sync-client.js +180 -0
- package/dist/cloud/lifeops-schedule-sync-client.js.map +11 -0
- package/dist/cloud/lifeops-schedule-sync-contracts.d.ts +89 -0
- package/dist/cloud/lifeops-schedule-sync-contracts.d.ts.map +1 -0
- package/dist/cloud/lifeops-schedule-sync-contracts.js +39 -0
- package/dist/cloud/lifeops-schedule-sync-contracts.js.map +10 -0
- package/dist/cloud/managed-payment-clients.d.ts +166 -0
- package/dist/cloud/managed-payment-clients.d.ts.map +1 -0
- package/dist/cloud/managed-payment-clients.js +238 -0
- package/dist/cloud/managed-payment-clients.js.map +11 -0
- package/dist/cloud/null-observer.d.ts +35 -0
- package/dist/cloud/null-observer.d.ts.map +1 -0
- package/dist/cloud/null-observer.js +45 -0
- package/dist/cloud/null-observer.js.map +10 -0
- package/dist/cloud/setup-observer.d.ts +98 -0
- package/dist/cloud/setup-observer.d.ts.map +1 -0
- package/dist/cloud/setup-observer.js +2 -0
- package/dist/cloud/setup-observer.js.map +9 -0
- package/dist/cloud/validate-url.d.ts.map +1 -1
- package/dist/cloud/validate-url.js +2 -1
- package/dist/cloud/validate-url.js.map +3 -3
- package/dist/cloud/x402-payment-handler.d.ts +85 -0
- package/dist/cloud/x402-payment-handler.d.ts.map +1 -0
- package/dist/cloud/x402-payment-handler.js +119 -0
- package/dist/cloud/x402-payment-handler.js.map +10 -0
- package/dist/cloud-setup.d.ts +36 -0
- package/dist/cloud-setup.d.ts.map +1 -0
- package/dist/{onboarding.js → cloud-setup.js} +139 -139
- package/dist/cloud-setup.js.map +14 -0
- package/dist/cloud-voice-catalog.d.ts +65 -0
- package/dist/cloud-voice-catalog.d.ts.map +1 -0
- package/dist/cloud-voice-catalog.js +278 -0
- package/dist/cloud-voice-catalog.js.map +12 -0
- package/dist/index.browser.d.ts +11 -0
- package/dist/index.browser.d.ts.map +1 -1
- package/dist/index.d.ts +7 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5416 -8405
- package/dist/index.js.map +48 -116
- package/dist/index.node.d.ts +8 -1
- package/dist/index.node.d.ts.map +1 -1
- package/dist/init.js +17 -4
- package/dist/init.js.map +4 -4
- package/dist/lib/cloud-connection.d.ts +0 -1
- package/dist/lib/cloud-connection.d.ts.map +1 -1
- package/dist/lib/cloud-connection.js +14 -91
- package/dist/lib/cloud-connection.js.map +7 -7
- package/dist/lib/cloud-secrets.d.ts +5 -18
- package/dist/lib/cloud-secrets.d.ts.map +1 -1
- package/dist/lib/cloud-secrets.js +8 -36
- package/dist/lib/cloud-secrets.js.map +3 -3
- package/dist/lib/config-like.d.ts +1 -1
- package/dist/lib/config-like.d.ts.map +1 -1
- package/dist/lib/config-like.js +3 -3
- package/dist/lib/config-like.js.map +3 -3
- package/dist/lib/credential-type-map.d.ts +1 -1
- package/dist/lib/credential-type-map.js.map +1 -1
- package/dist/lib/http.d.ts +0 -11
- package/dist/lib/http.d.ts.map +1 -1
- package/dist/lib/http.js.map +2 -2
- package/dist/lib/server-cloud-tts.d.ts +12 -25
- package/dist/lib/server-cloud-tts.d.ts.map +1 -1
- package/dist/lib/server-cloud-tts.js +31 -329
- package/dist/lib/server-cloud-tts.js.map +4 -7
- package/dist/lib/tts-debug.d.ts +5 -3
- package/dist/lib/tts-debug.d.ts.map +1 -1
- package/dist/lib/tts-debug.js +1 -34
- package/dist/lib/tts-debug.js.map +3 -4
- package/dist/models/embeddings.d.ts.map +1 -1
- package/dist/models/embeddings.js +79 -69
- package/dist/models/embeddings.js.map +6 -6
- package/dist/models/image.d.ts.map +1 -1
- package/dist/models/image.js +42 -15
- package/dist/models/image.js.map +6 -6
- package/dist/models/index.js +676 -166
- package/dist/models/index.js.map +11 -12
- package/dist/models/research.d.ts.map +1 -1
- package/dist/models/research.js +24 -7
- package/dist/models/research.js.map +6 -6
- package/dist/models/speech.d.ts +61 -3
- package/dist/models/speech.d.ts.map +1 -1
- package/dist/models/speech.js +173 -17
- package/dist/models/speech.js.map +5 -5
- package/dist/models/text.d.ts +106 -1
- package/dist/models/text.d.ts.map +1 -1
- package/dist/models/text.js +452 -82
- package/dist/models/text.js.map +7 -8
- package/dist/models/tokenization.d.ts.map +1 -1
- package/dist/models/tokenization.js.map +2 -2
- package/dist/models/transcription.d.ts.map +1 -1
- package/dist/models/transcription.js +20 -6
- package/dist/models/transcription.js.map +5 -5
- package/dist/node/index.node.js +2828 -5838
- package/dist/node/index.node.js.map +47 -116
- package/dist/plugin.d.ts.map +1 -1
- package/dist/plugin.js +376 -5050
- package/dist/plugin.js.map +16 -92
- package/dist/providers/openai.js +11 -2
- package/dist/providers/openai.js.map +3 -3
- package/dist/register-routes.js +376 -5050
- package/dist/register-routes.js.map +16 -92
- package/dist/routes/cloud-billing-routes.d.ts.map +1 -1
- package/dist/routes/cloud-billing-routes.js +17 -60
- package/dist/routes/cloud-billing-routes.js.map +8 -7
- package/dist/routes/cloud-coding-container-routes.d.ts +8 -0
- package/dist/routes/cloud-coding-container-routes.d.ts.map +1 -0
- package/dist/routes/cloud-coding-container-routes.js +214 -0
- package/dist/routes/cloud-coding-container-routes.js.map +11 -0
- package/dist/routes/cloud-compat-routes.d.ts.map +1 -1
- package/dist/routes/cloud-compat-routes.js +17 -60
- package/dist/routes/cloud-compat-routes.js.map +8 -7
- package/dist/routes/cloud-features-routes.js +2 -2
- package/dist/routes/cloud-features-routes.js.map +4 -4
- package/dist/routes/cloud-relay-routes.d.ts +2 -1
- package/dist/routes/cloud-relay-routes.d.ts.map +1 -1
- package/dist/routes/cloud-relay-routes.js +84 -2
- package/dist/routes/cloud-relay-routes.js.map +5 -4
- package/dist/routes/cloud-routes-autonomous.d.ts +3 -4
- package/dist/routes/cloud-routes-autonomous.d.ts.map +1 -1
- package/dist/routes/cloud-routes-autonomous.js +11 -4893
- package/dist/routes/cloud-routes-autonomous.js.map +8 -87
- package/dist/routes/cloud-routes.d.ts +2 -2
- package/dist/routes/cloud-routes.d.ts.map +1 -1
- package/dist/routes/cloud-routes.js +343 -5058
- package/dist/routes/cloud-routes.js.map +13 -90
- package/dist/routes/cloud-status-routes-autonomous.d.ts +1 -2
- package/dist/routes/cloud-status-routes-autonomous.d.ts.map +1 -1
- package/dist/routes/cloud-status-routes-autonomous.js +4 -51
- package/dist/routes/cloud-status-routes-autonomous.js.map +5 -5
- package/dist/routes/cloud-status-routes.js +14 -90
- package/dist/routes/cloud-status-routes.js.map +7 -7
- package/dist/routes/home-remote-runner-access-url.d.ts +16 -0
- package/dist/routes/home-remote-runner-access-url.d.ts.map +1 -0
- package/dist/routes/home-remote-runner-access-url.js +91 -0
- package/dist/routes/home-remote-runner-access-url.js.map +10 -0
- package/dist/routes/travel-provider-relay-routes.d.ts +9 -0
- package/dist/routes/travel-provider-relay-routes.d.ts.map +1 -0
- package/dist/routes/travel-provider-relay-routes.js +358 -0
- package/dist/routes/travel-provider-relay-routes.js.map +14 -0
- package/dist/services/cloud-auth.d.ts +1 -1
- package/dist/services/cloud-auth.d.ts.map +1 -1
- package/dist/services/cloud-auth.js +7 -2
- package/dist/services/cloud-auth.js.map +4 -4
- package/dist/services/cloud-backup.js.map +2 -2
- package/dist/services/cloud-bootstrap.d.ts.map +1 -1
- package/dist/services/cloud-bootstrap.js.map +2 -2
- package/dist/services/cloud-bridge.js.map +3 -3
- package/dist/services/cloud-container.d.ts +5 -1
- package/dist/services/cloud-container.d.ts.map +1 -1
- package/dist/services/cloud-container.js +52 -1
- package/dist/services/cloud-container.js.map +4 -4
- package/dist/services/cloud-credential-provider.js.map +2 -2
- package/dist/services/cloud-model-registry.js.map +2 -2
- package/dist/types/cloud.d.ts +1 -0
- package/dist/types/cloud.d.ts.map +1 -1
- package/dist/types/cloud.js.map +2 -2
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/utils/cloud-sdk/client.d.ts.map +1 -1
- package/dist/utils/cloud-sdk/client.js +136 -4
- package/dist/utils/cloud-sdk/client.js.map +5 -5
- package/dist/utils/cloud-sdk/http.js.map +1 -1
- package/dist/utils/cloud-sdk/public-routes.d.ts +186 -0
- package/dist/utils/cloud-sdk/public-routes.d.ts.map +1 -1
- package/dist/utils/cloud-sdk/public-routes.js +99 -1
- package/dist/utils/cloud-sdk/public-routes.js.map +3 -3
- package/dist/utils/cloud-sdk/types.d.ts +0 -2
- package/dist/utils/cloud-sdk/types.d.ts.map +1 -1
- package/dist/utils/cloud-sdk/types.js.map +1 -1
- package/dist/utils/config.d.ts +10 -1
- package/dist/utils/config.d.ts.map +1 -1
- package/dist/utils/config.js +12 -2
- package/dist/utils/config.js.map +3 -3
- package/dist/utils/events.d.ts +23 -2
- package/dist/utils/events.d.ts.map +1 -1
- package/dist/utils/events.js +5 -3
- package/dist/utils/events.js.map +3 -3
- package/dist/utils/sdk-client.d.ts.map +1 -1
- package/dist/utils/sdk-client.js +17 -4
- package/dist/utils/sdk-client.js.map +4 -4
- package/dist/utils/waifu-metering.d.ts +108 -0
- package/dist/utils/waifu-metering.d.ts.map +1 -0
- package/dist/utils/waifu-metering.js +166 -0
- package/dist/utils/waifu-metering.js.map +10 -0
- package/package.json +51 -22
- package/src/cloud/auth-service-types.ts +24 -0
- package/src/cloud/base-url.ts +6 -62
- package/src/cloud/clack-observer.ts +189 -0
- package/src/cloud/duffel-client.ts +847 -0
- package/src/cloud/index.ts +10 -0
- package/src/cloud/lifeops-schedule-sync-client.ts +245 -0
- package/src/cloud/lifeops-schedule-sync-contracts.ts +124 -0
- package/src/cloud/managed-payment-clients.ts +374 -0
- package/src/cloud/null-observer.ts +45 -0
- package/src/cloud/setup-observer.ts +125 -0
- package/src/cloud/validate-url.ts +7 -1
- package/src/cloud/x402-payment-handler.ts +215 -0
- package/src/cloud-setup.ts +531 -0
- package/src/cloud-voice-catalog.test.ts +254 -0
- package/src/cloud-voice-catalog.ts +246 -0
- package/src/index.browser.ts +29 -0
- package/src/index.node.ts +31 -1
- package/src/index.ts +76 -4
- package/src/lib/cloud-connection.ts +2 -4
- package/src/lib/cloud-secrets.ts +10 -54
- package/src/lib/config-like.ts +1 -1
- package/src/lib/credential-type-map.ts +2 -2
- package/src/lib/http.ts +0 -17
- package/src/lib/server-cloud-tts.ts +33 -341
- package/src/lib/tts-debug.ts +5 -34
- package/src/models/embeddings.ts +140 -76
- package/src/models/image.ts +29 -14
- package/src/models/research.ts +11 -1
- package/src/models/speech.ts +269 -23
- package/src/models/text.ts +704 -110
- package/src/models/tokenization.ts +2 -2
- package/src/models/transcription.ts +7 -3
- package/src/plugin.ts +38 -0
- package/src/routes/cloud-billing-routes.ts +4 -14
- package/src/routes/cloud-coding-container-routes.ts +198 -0
- package/src/routes/cloud-compat-routes.ts +4 -14
- package/src/routes/cloud-features-routes.ts +1 -1
- package/src/routes/cloud-relay-routes.ts +47 -1
- package/src/routes/cloud-routes-autonomous.ts +7 -10
- package/src/routes/cloud-routes.ts +68 -7
- package/src/routes/cloud-status-routes-autonomous.ts +6 -2
- package/src/routes/home-remote-runner-access-url.ts +83 -0
- package/src/routes/travel-provider-relay-routes.ts +193 -0
- package/src/services/cloud-auth.ts +9 -2
- package/src/services/cloud-bootstrap.ts +1 -3
- package/src/services/cloud-bridge.ts +1 -1
- package/src/services/cloud-container.ts +93 -0
- package/src/services/cloud-credential-provider.ts +1 -1
- package/src/services/cloud-model-registry.ts +1 -1
- package/src/types/cloud.ts +22 -0
- package/src/types/index.ts +19 -0
- package/src/utils/cloud-sdk/client.ts +42 -3
- package/src/utils/cloud-sdk/public-routes.ts +168 -0
- package/src/utils/cloud-sdk/types.ts +0 -2
- package/src/utils/config.ts +20 -1
- package/src/utils/events.ts +30 -2
- package/src/utils/sdk-client.ts +5 -1
- package/src/utils/waifu-metering.ts +302 -0
- package/dist/onboarding.d.ts +0 -35
- package/dist/onboarding.d.ts.map +0 -1
- package/dist/onboarding.js.map +0 -14
- package/src/onboarding.ts +0 -396
package/src/models/embeddings.ts
CHANGED
|
@@ -1,10 +1,54 @@
|
|
|
1
1
|
import type { IAgentRuntime, TextEmbeddingParams } from "@elizaos/core";
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
logger,
|
|
4
|
+
ModelType,
|
|
5
|
+
timeInferenceSpan,
|
|
6
|
+
VECTOR_DIMS,
|
|
7
|
+
} from "@elizaos/core";
|
|
3
8
|
import { getSetting } from "../utils/config";
|
|
4
9
|
import { emitModelUsageEvent } from "../utils/events";
|
|
5
10
|
import { createCloudApiClient } from "../utils/sdk-client";
|
|
6
11
|
|
|
7
12
|
const MAX_BATCH_SIZE = 100;
|
|
13
|
+
|
|
14
|
+
// ── Bounded retry/backoff for the /embeddings round-trip ──────────────────
|
|
15
|
+
// Embeddings are off the turn's critical path (queueEmbeddingGeneration is
|
|
16
|
+
// fire-and-forget), so a stall here delays the embedding QUEUE, not a reply.
|
|
17
|
+
// The old behaviour — one blind 30s (or full retry-after) sleep then a single
|
|
18
|
+
// retry — could park the queue for 30s+ on a transient 429. Replaced with
|
|
19
|
+
// bounded exponential backoff + jitter, a CAP on any single wait (so a large
|
|
20
|
+
// server retry-after can't stall the queue indefinitely), and a per-request
|
|
21
|
+
// client-side timeout (the endpoint had none, so a hung gateway hung the
|
|
22
|
+
// queue forever).
|
|
23
|
+
//
|
|
24
|
+
// Handler retries are deliberately SMALL: the EmbeddingGenerationService
|
|
25
|
+
// BatchQueue already wraps generateEmbedding in its own multi-attempt backoff,
|
|
26
|
+
// so this layer absorbs only a single transient burst (one quick retry) and
|
|
27
|
+
// defers sustained pressure to the queue — otherwise the two backoffs compound.
|
|
28
|
+
const EMBED_MAX_ATTEMPTS = 2;
|
|
29
|
+
const EMBED_BACKOFF_BASE_MS = 1_000;
|
|
30
|
+
const EMBED_BACKOFF_CAP_MS = 8_000;
|
|
31
|
+
const EMBED_REQUEST_TIMEOUT_MS = 60_000;
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Backoff before the next embedding attempt. Exponential (base·2^attempt) as a
|
|
35
|
+
* floor, honoring the server's `retry-after` when present, but never longer
|
|
36
|
+
* than {@link EMBED_BACKOFF_CAP_MS}; ±25% jitter spreads retries from a burst.
|
|
37
|
+
*/
|
|
38
|
+
function embeddingBackoffMs(attempt: number, retryAfterSec?: number): number {
|
|
39
|
+
const exp = EMBED_BACKOFF_BASE_MS * 2 ** attempt;
|
|
40
|
+
const serverHint =
|
|
41
|
+
typeof retryAfterSec === "number" && retryAfterSec > 0
|
|
42
|
+
? retryAfterSec * 1000
|
|
43
|
+
: 0;
|
|
44
|
+
const base = Math.min(EMBED_BACKOFF_CAP_MS, Math.max(exp, serverHint));
|
|
45
|
+
return Math.round(base * (1 + Math.random() * 0.25));
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function sleep(ms: number): Promise<void> {
|
|
49
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
50
|
+
}
|
|
51
|
+
|
|
8
52
|
function extractRateLimitInfo(response: Response): {
|
|
9
53
|
remainingRequests?: number;
|
|
10
54
|
remainingTokens?: number;
|
|
@@ -48,9 +92,16 @@ function getEmbeddingConfig(runtime: IAgentRuntime) {
|
|
|
48
92
|
return { embeddingModelName, embeddingDimension };
|
|
49
93
|
}
|
|
50
94
|
|
|
51
|
-
|
|
95
|
+
/**
|
|
96
|
+
* The init probe vector. `runtime.ensureEmbeddingDimension()` calls the handler
|
|
97
|
+
* with `null` purely to learn the vector length; it only inspects `.length`, so
|
|
98
|
+
* a deterministic non-zero[0] marker vector is the correct, legitimate response.
|
|
99
|
+
* This is the ONLY place a synthetic vector is returned — every real failure
|
|
100
|
+
* throws so it can never be persisted as a corrupt embedding (Commandment 8).
|
|
101
|
+
*/
|
|
102
|
+
function createInitProbeVector(dimension: number): number[] {
|
|
52
103
|
const vector = Array(dimension).fill(0);
|
|
53
|
-
vector[0] =
|
|
104
|
+
vector[0] = 0.1;
|
|
54
105
|
return vector;
|
|
55
106
|
}
|
|
56
107
|
|
|
@@ -66,7 +117,7 @@ export async function handleTextEmbedding(
|
|
|
66
117
|
|
|
67
118
|
if (params === null) {
|
|
68
119
|
logger.debug("Creating test embedding for initialization");
|
|
69
|
-
return
|
|
120
|
+
return createInitProbeVector(embeddingDimension);
|
|
70
121
|
}
|
|
71
122
|
|
|
72
123
|
let text: string;
|
|
@@ -75,13 +126,14 @@ export async function handleTextEmbedding(
|
|
|
75
126
|
} else if (typeof params === "object" && params.text) {
|
|
76
127
|
text = params.text;
|
|
77
128
|
} else {
|
|
78
|
-
|
|
79
|
-
|
|
129
|
+
// A malformed request is a programming error, not a recoverable runtime
|
|
130
|
+
// state. Throw instead of returning a marker vector that would silently
|
|
131
|
+
// corrupt the embedding store (Commandment 8).
|
|
132
|
+
throw new Error("Invalid input format for embedding: expected string or { text: string }");
|
|
80
133
|
}
|
|
81
134
|
|
|
82
135
|
if (!text.trim()) {
|
|
83
|
-
|
|
84
|
-
return createErrorVector(embeddingDimension, 0.3);
|
|
136
|
+
throw new Error("Cannot generate embedding for empty text");
|
|
85
137
|
}
|
|
86
138
|
|
|
87
139
|
const results = await handleBatchTextEmbedding(runtime, [text]);
|
|
@@ -103,26 +155,22 @@ export async function handleBatchTextEmbedding(
|
|
|
103
155
|
const client = createCloudApiClient(runtime, true);
|
|
104
156
|
|
|
105
157
|
if (!texts || texts.length === 0) {
|
|
106
|
-
logger.warn("[BatchEmbeddings] Empty texts array");
|
|
107
158
|
return [];
|
|
108
159
|
}
|
|
109
160
|
|
|
161
|
+
// Every text must be non-empty: an empty input cannot produce a meaningful
|
|
162
|
+
// vector, and a marker/zero vector would silently corrupt the store. Surface
|
|
163
|
+
// the bad input to the caller (Commandment 8) instead of papering over it.
|
|
110
164
|
const validTexts: { text: string; originalIndex: number }[] = [];
|
|
111
|
-
const results: number[][] = new Array(texts.length);
|
|
112
|
-
|
|
113
165
|
for (let i = 0; i < texts.length; i++) {
|
|
114
166
|
const text = texts[i]?.trim();
|
|
115
|
-
if (text) {
|
|
116
|
-
|
|
117
|
-
} else {
|
|
118
|
-
results[i] = createErrorVector(embeddingDimension, 0.3);
|
|
167
|
+
if (!text) {
|
|
168
|
+
throw new Error(`Cannot generate embedding for empty text at index ${i}`);
|
|
119
169
|
}
|
|
170
|
+
validTexts.push({ text, originalIndex: i });
|
|
120
171
|
}
|
|
121
172
|
|
|
122
|
-
|
|
123
|
-
logger.warn("[BatchEmbeddings] All texts were empty");
|
|
124
|
-
return results;
|
|
125
|
-
}
|
|
173
|
+
const results: number[][] = new Array(texts.length);
|
|
126
174
|
|
|
127
175
|
for (let batchStart = 0; batchStart < validTexts.length; batchStart += MAX_BATCH_SIZE) {
|
|
128
176
|
const batchEnd = Math.min(batchStart + MAX_BATCH_SIZE, validTexts.length);
|
|
@@ -134,74 +182,88 @@ export async function handleBatchTextEmbedding(
|
|
|
134
182
|
);
|
|
135
183
|
|
|
136
184
|
try {
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
185
|
+
// Records a `cloud.embedding` span on the active per-turn timer when an
|
|
186
|
+
// embedding happens to be on a turn's critical path (most are queued /
|
|
187
|
+
// detached, so this is a no-op there — which is exactly what proves they
|
|
188
|
+
// don't add to turn latency). Retries transient throttling/5xx with
|
|
189
|
+
// bounded exponential backoff (see EMBED_* constants) instead of a single
|
|
190
|
+
// 30s blind sleep.
|
|
191
|
+
let response: Response | null = null;
|
|
192
|
+
for (let attempt = 0; attempt < EMBED_MAX_ATTEMPTS; attempt++) {
|
|
193
|
+
const resp = await timeInferenceSpan(
|
|
194
|
+
"cloud.embedding",
|
|
195
|
+
() =>
|
|
196
|
+
client.requestRaw("POST", "/embeddings", {
|
|
197
|
+
json: {
|
|
198
|
+
model: embeddingModelName,
|
|
199
|
+
input: batchTexts,
|
|
200
|
+
},
|
|
201
|
+
timeoutMs: EMBED_REQUEST_TIMEOUT_MS,
|
|
202
|
+
}),
|
|
203
|
+
{ batch: batchTexts.length, attempt }
|
|
149
204
|
);
|
|
150
|
-
}
|
|
151
205
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
input: batchTexts,
|
|
161
|
-
},
|
|
162
|
-
});
|
|
163
|
-
|
|
164
|
-
if (!retryResponse.ok) {
|
|
165
|
-
logger.error(`[BatchEmbeddings] Retry failed: ${retryResponse.status}`);
|
|
166
|
-
for (const item of batch) {
|
|
167
|
-
results[item.originalIndex] = createErrorVector(embeddingDimension, 0.4);
|
|
168
|
-
}
|
|
169
|
-
continue;
|
|
206
|
+
const rateLimitInfo = extractRateLimitInfo(resp);
|
|
207
|
+
if (
|
|
208
|
+
rateLimitInfo.remainingRequests !== undefined &&
|
|
209
|
+
rateLimitInfo.remainingRequests < 50
|
|
210
|
+
) {
|
|
211
|
+
logger.warn(
|
|
212
|
+
`[BatchEmbeddings] Rate limit: ${rateLimitInfo.remainingRequests}/${rateLimitInfo.limitRequests} requests remaining`
|
|
213
|
+
);
|
|
170
214
|
}
|
|
171
215
|
|
|
172
|
-
const
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
216
|
+
const transient =
|
|
217
|
+
resp.status === 429 ||
|
|
218
|
+
resp.status === 502 ||
|
|
219
|
+
resp.status === 503 ||
|
|
220
|
+
resp.status === 504;
|
|
221
|
+
if (transient && attempt < EMBED_MAX_ATTEMPTS - 1) {
|
|
222
|
+
const delay = embeddingBackoffMs(attempt, rateLimitInfo.retryAfter);
|
|
223
|
+
logger.warn(
|
|
224
|
+
`[BatchEmbeddings] ${resp.status} (attempt ${attempt + 1}/${EMBED_MAX_ATTEMPTS}) — backing off ${delay}ms`
|
|
225
|
+
);
|
|
226
|
+
// Drain the body so the underlying connection can be reused.
|
|
227
|
+
await resp.text().catch(() => undefined);
|
|
228
|
+
await sleep(delay);
|
|
229
|
+
continue;
|
|
182
230
|
}
|
|
183
|
-
|
|
231
|
+
response = resp;
|
|
232
|
+
break;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// Type guard: the loop assigns `response` on its final iteration, so this
|
|
236
|
+
// is unreachable in practice.
|
|
237
|
+
if (!response) {
|
|
238
|
+
throw new Error("[BatchEmbeddings] No response after retry loop");
|
|
184
239
|
}
|
|
185
240
|
|
|
186
241
|
if (!response.ok) {
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
242
|
+
// Auth errors (401/403) are non-recoverable with the current key.
|
|
243
|
+
// Every other non-OK status is just as fatal for this batch — neither
|
|
244
|
+
// can produce real vectors. Throw in both cases so the router falls
|
|
245
|
+
// through to the next provider (e.g. local inference) instead of
|
|
246
|
+
// silently persisting marker/zero vectors that corrupt the embedding
|
|
247
|
+
// store. Commandment 8: don't hide broken pipelines behind fallbacks.
|
|
248
|
+
if (response.status === 401 || response.status === 403) {
|
|
249
|
+
throw new Error(
|
|
250
|
+
`[BatchEmbeddings] Authentication failed (${response.status}). ` +
|
|
251
|
+
`Check ELIZAOS_CLOUD_API_KEY or ELIZAOS_CLOUD_EMBEDDING_API_KEY — ` +
|
|
252
|
+
`the current key is not authorized for the embedding endpoint.`
|
|
253
|
+
);
|
|
190
254
|
}
|
|
191
|
-
|
|
255
|
+
throw new Error(
|
|
256
|
+
`[BatchEmbeddings] API error: ${response.status} ${response.statusText}`
|
|
257
|
+
);
|
|
192
258
|
}
|
|
193
259
|
|
|
194
260
|
const data = (await response.json()) as {
|
|
195
|
-
data
|
|
261
|
+
data?: Array<{ embedding: number[]; index: number }>;
|
|
196
262
|
usage?: { prompt_tokens: number; total_tokens: number };
|
|
197
263
|
};
|
|
198
264
|
|
|
199
265
|
if (!data?.data || !Array.isArray(data.data)) {
|
|
200
|
-
|
|
201
|
-
for (const item of batch) {
|
|
202
|
-
results[item.originalIndex] = createErrorVector(embeddingDimension, 0.5);
|
|
203
|
-
}
|
|
204
|
-
continue;
|
|
266
|
+
throw new Error("[BatchEmbeddings] API returned invalid response structure");
|
|
205
267
|
}
|
|
206
268
|
|
|
207
269
|
for (const item of data.data) {
|
|
@@ -219,14 +281,16 @@ export async function handleBatchTextEmbedding(
|
|
|
219
281
|
}
|
|
220
282
|
|
|
221
283
|
logger.debug(
|
|
222
|
-
`[BatchEmbeddings] Got ${batch.length} embeddings (${embeddingDimension}d)
|
|
284
|
+
`[BatchEmbeddings] Got ${batch.length} embeddings (${embeddingDimension}d)`
|
|
223
285
|
);
|
|
224
286
|
} catch (error) {
|
|
287
|
+
// Any failure in this batch (HTTP error, transport error, malformed body)
|
|
288
|
+
// means we have no real vectors for it. Log context and re-throw so the
|
|
289
|
+
// router can fall through to another provider; never persist marker/zero
|
|
290
|
+
// vectors that would corrupt the embedding store (Commandment 8).
|
|
225
291
|
const message = error instanceof Error ? error.message : String(error);
|
|
226
|
-
logger.error(`[BatchEmbeddings]
|
|
227
|
-
|
|
228
|
-
results[item.originalIndex] = createErrorVector(embeddingDimension, 0.6);
|
|
229
|
-
}
|
|
292
|
+
logger.error(`[BatchEmbeddings] Batch failed: ${message}`);
|
|
293
|
+
throw error instanceof Error ? error : new Error(message);
|
|
230
294
|
}
|
|
231
295
|
}
|
|
232
296
|
|
package/src/models/image.ts
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import type { IAgentRuntime, ImageDescriptionParams, ImageGenerationParams } from "@elizaos/core";
|
|
2
2
|
import { logger, ModelType } from "@elizaos/core";
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
getImageDescriptionModel,
|
|
5
|
+
getImageGenerationModel,
|
|
6
|
+
getSetting,
|
|
7
|
+
resolveCloudTimeoutMs,
|
|
8
|
+
} from "../utils/config";
|
|
4
9
|
import { emitModelUsageEvent } from "../utils/events";
|
|
5
10
|
import { parseImageDescriptionResponse } from "../utils/helpers";
|
|
6
11
|
import { createElizaCloudClient } from "../utils/sdk-client";
|
|
@@ -32,7 +37,7 @@ export async function handleImageGeneration(
|
|
|
32
37
|
|
|
33
38
|
const typedData = await createElizaCloudClient(runtime).generateImage(requestBody);
|
|
34
39
|
|
|
35
|
-
const result = typedData.images.map((img) => ({
|
|
40
|
+
const result = typedData.images.map((img: { url?: string; image?: string }) => ({
|
|
36
41
|
url: img.url ?? img.image ?? "",
|
|
37
42
|
}));
|
|
38
43
|
return result;
|
|
@@ -55,11 +60,10 @@ export async function handleImageDescription(
|
|
|
55
60
|
// every other caller (agent-orchestrator's task validator, vision, lifeops,
|
|
56
61
|
// farcaster, telegram) free to spend the rate-limit budget.
|
|
57
62
|
const disableSetting = getSetting(runtime, "DISABLE_IMAGE_DESCRIPTION", "");
|
|
58
|
-
const disabled =
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
process.env.DISABLE_IMAGE_DESCRIPTION === "1";
|
|
63
|
+
const disabled = [disableSetting, process.env.DISABLE_IMAGE_DESCRIPTION].some((value) => {
|
|
64
|
+
const normalized = value?.trim().toLowerCase();
|
|
65
|
+
return normalized === "1" || normalized === "true" || normalized === "yes" || normalized === "on";
|
|
66
|
+
});
|
|
63
67
|
if (disabled) {
|
|
64
68
|
logger.debug("[ELIZAOS_CLOUD] IMAGE_DESCRIPTION skipped — DISABLE_IMAGE_DESCRIPTION is set");
|
|
65
69
|
return {
|
|
@@ -115,22 +119,27 @@ export async function handleImageDescription(
|
|
|
115
119
|
let response: Response | null = null;
|
|
116
120
|
let attemptedRetry = false;
|
|
117
121
|
for (let attempt = 0; attempt < 2; attempt++) {
|
|
118
|
-
|
|
122
|
+
const attemptResponse = await client.routes.postApiV1ChatCompletionsRaw({
|
|
119
123
|
json: requestBody,
|
|
124
|
+
timeoutMs: resolveCloudTimeoutMs("ELIZAOS_CLOUD_IMAGE_TIMEOUT_MS", 120_000),
|
|
120
125
|
});
|
|
121
|
-
if (
|
|
126
|
+
if (!attemptResponse) {
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
response = attemptResponse;
|
|
130
|
+
if (attemptResponse.status !== 429 || attemptedRetry) break;
|
|
122
131
|
|
|
123
132
|
// `Number(null) === 0`, so guard against a missing header before
|
|
124
133
|
// calling `Number(...)` — otherwise the header path always wins with a
|
|
125
134
|
// bogus `0` and the body fallback becomes unreachable.
|
|
126
|
-
const headerValue =
|
|
135
|
+
const headerValue = attemptResponse.headers.get("retry-after");
|
|
127
136
|
const headerRetryAfter =
|
|
128
137
|
headerValue !== null && Number.isFinite(Number(headerValue))
|
|
129
138
|
? Number(headerValue)
|
|
130
139
|
: undefined;
|
|
131
140
|
let bodyRetryAfter: number | undefined;
|
|
132
141
|
try {
|
|
133
|
-
const peek = (await
|
|
142
|
+
const peek = (await attemptResponse.clone().json()) as {
|
|
134
143
|
retryAfter?: unknown;
|
|
135
144
|
};
|
|
136
145
|
bodyRetryAfter =
|
|
@@ -157,8 +166,14 @@ export async function handleImageDescription(
|
|
|
157
166
|
break;
|
|
158
167
|
}
|
|
159
168
|
|
|
160
|
-
if (!response
|
|
161
|
-
|
|
169
|
+
if (!response) {
|
|
170
|
+
throw new Error("ElizaOS Cloud API did not return a response");
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
const finalResponse = response;
|
|
174
|
+
|
|
175
|
+
if (!finalResponse.ok) {
|
|
176
|
+
const status = finalResponse.status;
|
|
162
177
|
if (status === 402) {
|
|
163
178
|
throw new Error(
|
|
164
179
|
"Eliza Cloud credits exhausted — top up at https://www.elizacloud.ai/dashboard/settings?tab=billing"
|
|
@@ -184,7 +199,7 @@ export async function handleImageDescription(
|
|
|
184
199
|
};
|
|
185
200
|
};
|
|
186
201
|
|
|
187
|
-
const typedResult = (await
|
|
202
|
+
const typedResult = (await finalResponse.json()) as OpenAIResponseType;
|
|
188
203
|
const content = typedResult.choices?.[0]?.message?.content;
|
|
189
204
|
|
|
190
205
|
if (typedResult.usage) {
|
package/src/models/research.ts
CHANGED
|
@@ -8,10 +8,16 @@ import type {
|
|
|
8
8
|
ResearchResult,
|
|
9
9
|
} from "@elizaos/core";
|
|
10
10
|
import { logger, ModelType } from "@elizaos/core";
|
|
11
|
-
import { getResearchModel } from "../utils/config";
|
|
11
|
+
import { getResearchModel, resolveCloudTimeoutMs } from "../utils/config";
|
|
12
12
|
import { emitModelUsageEvent } from "../utils/events";
|
|
13
13
|
import { createCloudApiClient } from "../utils/sdk-client";
|
|
14
14
|
|
|
15
|
+
// Deep research is a long-running, TURN-BLOCKING call; without a timeout a
|
|
16
|
+
// stalled gateway hangs the turn forever (cloud-sdk applies no default). The
|
|
17
|
+
// default is deliberately generous (10 min) so a legitimately slow run isn't
|
|
18
|
+
// aborted; `ELIZAOS_CLOUD_RESEARCH_TIMEOUT_MS=0` opts out.
|
|
19
|
+
const DEFAULT_RESEARCH_TIMEOUT_MS = 600_000;
|
|
20
|
+
|
|
15
21
|
interface ResponsesAPIOutput {
|
|
16
22
|
id: string;
|
|
17
23
|
status: string;
|
|
@@ -221,6 +227,10 @@ export async function handleResearch(
|
|
|
221
227
|
|
|
222
228
|
const response = await createCloudApiClient(runtime).requestRaw("POST", "/responses", {
|
|
223
229
|
json: requestBody,
|
|
230
|
+
timeoutMs: resolveCloudTimeoutMs(
|
|
231
|
+
"ELIZAOS_CLOUD_RESEARCH_TIMEOUT_MS",
|
|
232
|
+
DEFAULT_RESEARCH_TIMEOUT_MS
|
|
233
|
+
),
|
|
224
234
|
});
|
|
225
235
|
|
|
226
236
|
if (!response.ok) {
|