@elizaos/plugin-elizacloud 2.0.0-beta.1 → 2.0.3-beta.2
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 +2888 -5918
- 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 +881 -3
- package/dist/cloud/index.js.map +9 -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 +5427 -8410
- package/dist/index.js.map +47 -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 +7 -0
- package/dist/models/embeddings.d.ts.map +1 -1
- package/dist/models/embeddings.js +95 -73
- 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 +689 -169
- 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 +113 -1
- package/dist/models/text.d.ts.map +1 -1
- package/dist/models/text.js +453 -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 +2842 -5841
- 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 +81 -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 +178 -78
- 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/dist/cloud/index.js
CHANGED
|
@@ -15,16 +15,894 @@ var __export = (target, all) => {
|
|
|
15
15
|
};
|
|
16
16
|
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
17
17
|
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
18
|
+
|
|
19
|
+
// src/cloud/base-url.ts
|
|
20
|
+
import { normalizeCloudSiteUrl, resolveCloudApiBaseUrl } from "@elizaos/shared";
|
|
21
|
+
var init_base_url = () => {};
|
|
22
|
+
|
|
23
|
+
// src/cloud/x402-payment-handler.ts
|
|
24
|
+
import { logger } from "@elizaos/core";
|
|
25
|
+
function readString(value) {
|
|
26
|
+
if (typeof value !== "string")
|
|
27
|
+
return null;
|
|
28
|
+
const trimmed = value.trim();
|
|
29
|
+
return trimmed.length > 0 ? trimmed : null;
|
|
30
|
+
}
|
|
31
|
+
function readAmount(value) {
|
|
32
|
+
if (typeof value === "string") {
|
|
33
|
+
const trimmed = value.trim();
|
|
34
|
+
return trimmed.length > 0 ? trimmed : null;
|
|
35
|
+
}
|
|
36
|
+
if (typeof value === "number" && Number.isFinite(value)) {
|
|
37
|
+
return String(value);
|
|
38
|
+
}
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
function normalizeRequirement(raw) {
|
|
42
|
+
if (!raw || typeof raw !== "object")
|
|
43
|
+
return null;
|
|
44
|
+
const amount = readAmount(raw.amount);
|
|
45
|
+
const asset = readString(raw.asset);
|
|
46
|
+
const network = readString(raw.network);
|
|
47
|
+
const payTo = readString(raw.payTo);
|
|
48
|
+
if (!amount || !asset || !network || !payTo)
|
|
49
|
+
return null;
|
|
50
|
+
const scheme = readString(raw.scheme) ?? "exact";
|
|
51
|
+
return {
|
|
52
|
+
amount,
|
|
53
|
+
asset,
|
|
54
|
+
network,
|
|
55
|
+
payTo,
|
|
56
|
+
scheme,
|
|
57
|
+
expiresAt: readString(raw.expiresAt),
|
|
58
|
+
description: readString(raw.description)
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
function parseRequirementsArray(raw) {
|
|
62
|
+
if (!Array.isArray(raw))
|
|
63
|
+
return [];
|
|
64
|
+
const out = [];
|
|
65
|
+
for (const entry of raw) {
|
|
66
|
+
const normalized = normalizeRequirement(entry);
|
|
67
|
+
if (normalized)
|
|
68
|
+
out.push(normalized);
|
|
69
|
+
}
|
|
70
|
+
return out;
|
|
71
|
+
}
|
|
72
|
+
async function parseX402Response(response) {
|
|
73
|
+
const headerValue = response.headers.get("www-authenticate");
|
|
74
|
+
if (headerValue?.toLowerCase().startsWith("x402")) {
|
|
75
|
+
const jsonPart = headerValue.slice(4).trim();
|
|
76
|
+
if (jsonPart.length > 0) {
|
|
77
|
+
const parsed = JSON.parse(jsonPart);
|
|
78
|
+
const requirements2 = Array.isArray(parsed) ? parseRequirementsArray(parsed) : parseRequirementsArray(parsed.paymentRequirements ?? parsed.accepts);
|
|
79
|
+
if (requirements2.length > 0)
|
|
80
|
+
return requirements2;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
const cloned = response.clone();
|
|
84
|
+
const text = await cloned.text();
|
|
85
|
+
if (text.length === 0)
|
|
86
|
+
return null;
|
|
87
|
+
const body = JSON.parse(text);
|
|
88
|
+
const requirements = parseRequirementsArray(body.paymentRequirements ?? body.accepts);
|
|
89
|
+
return requirements.length > 0 ? requirements : null;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
class PaymentRequiredError extends Error {
|
|
93
|
+
code = "PAYMENT_REQUIRED";
|
|
94
|
+
requirements;
|
|
95
|
+
constructor(requirements, message) {
|
|
96
|
+
const text = message ?? `Eliza Cloud returned HTTP 402 — your credit balance can't cover this call. ${requirements.length} payment option(s) available.`;
|
|
97
|
+
super(text);
|
|
98
|
+
this.name = "PaymentRequiredError";
|
|
99
|
+
this.requirements = requirements;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
async function requestPayment(runtime, requirements) {
|
|
103
|
+
if (requirements.length === 0) {
|
|
104
|
+
throw new Error("[x402] requestPayment called with no requirements — adapter bug");
|
|
105
|
+
}
|
|
106
|
+
const preferred = requirements[0];
|
|
107
|
+
logger.warn({
|
|
108
|
+
boundary: "elizacloud",
|
|
109
|
+
integration: "x402",
|
|
110
|
+
asset: preferred.asset,
|
|
111
|
+
network: preferred.network,
|
|
112
|
+
amount: preferred.amount,
|
|
113
|
+
runtimeId: runtime.agentId
|
|
114
|
+
}, `[x402] payment-required: ${preferred.amount} ${preferred.asset} on ${preferred.network} → ${preferred.payTo}${preferred.description ? ` (${preferred.description})` : ""}`);
|
|
115
|
+
return { status: "surfaced", requirement: preferred, txId: null };
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// src/cloud/duffel-client.ts
|
|
119
|
+
import { logger as logger2 } from "@elizaos/core";
|
|
120
|
+
class DuffelConfigError extends Error {
|
|
121
|
+
code = "DUFFEL_NOT_CONFIGURED";
|
|
122
|
+
constructor(message) {
|
|
123
|
+
super(message);
|
|
124
|
+
this.name = "DuffelConfigError";
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
var DUFFEL_API_BASE_DEFAULT = "https://api.duffel.com";
|
|
128
|
+
var DUFFEL_API_VERSION = "v2";
|
|
129
|
+
var DEFAULT_CLOUD_RELAY_BASE = "http://127.0.0.1:31337";
|
|
130
|
+
var NOOP_DUFFEL_SPAN = {
|
|
131
|
+
success() {},
|
|
132
|
+
failure() {}
|
|
133
|
+
};
|
|
134
|
+
function getDuffelApiBase() {
|
|
135
|
+
return process.env.LIFEOPS_DUFFEL_API_BASE?.trim() || DUFFEL_API_BASE_DEFAULT;
|
|
136
|
+
}
|
|
137
|
+
function resolveDirectFlag(env) {
|
|
138
|
+
const value = env.ELIZA_DUFFEL_DIRECT?.trim().toLowerCase();
|
|
139
|
+
return value === "1" || value === "true";
|
|
140
|
+
}
|
|
141
|
+
function resolveLocalApiBase(env) {
|
|
142
|
+
const port = env.ELIZA_API_PORT?.trim();
|
|
143
|
+
if (port && /^\d+$/.test(port)) {
|
|
144
|
+
return `http://127.0.0.1:${port}`;
|
|
145
|
+
}
|
|
146
|
+
return DEFAULT_CLOUD_RELAY_BASE;
|
|
147
|
+
}
|
|
148
|
+
function readDuffelConfigFromEnv(env = process.env) {
|
|
149
|
+
if (resolveDirectFlag(env)) {
|
|
150
|
+
const apiKey = env.DUFFEL_API_KEY?.trim();
|
|
151
|
+
if (!apiKey) {
|
|
152
|
+
throw new DuffelConfigError("Duffel direct mode requested but DUFFEL_API_KEY is not set.");
|
|
153
|
+
}
|
|
154
|
+
return { mode: "direct", apiKey, cloudRelayBaseUrl: null };
|
|
155
|
+
}
|
|
156
|
+
return {
|
|
157
|
+
mode: "cloud",
|
|
158
|
+
apiKey: null,
|
|
159
|
+
cloudRelayBaseUrl: resolveLocalApiBase(env)
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
var DIRECT_MODE_COST = {
|
|
163
|
+
totalUsd: 0,
|
|
164
|
+
creatorMarkupUsd: 0,
|
|
165
|
+
platformFeeUsd: 0,
|
|
166
|
+
markupPercent: null,
|
|
167
|
+
metered: false
|
|
168
|
+
};
|
|
169
|
+
function buildHeaders(apiKey) {
|
|
170
|
+
return {
|
|
171
|
+
Authorization: `Bearer ${apiKey}`,
|
|
172
|
+
"Content-Type": "application/json",
|
|
173
|
+
"Duffel-Version": DUFFEL_API_VERSION,
|
|
174
|
+
Accept: "application/json"
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
function mapOffer(raw) {
|
|
178
|
+
const cabinClass = raw.slices[0]?.fare_brand_name ?? null;
|
|
179
|
+
const slices = raw.slices.map((slice) => ({
|
|
180
|
+
origin: slice.origin.iata_code,
|
|
181
|
+
destination: slice.destination.iata_code,
|
|
182
|
+
duration: slice.duration,
|
|
183
|
+
segments: slice.segments.map((seg) => ({
|
|
184
|
+
origin: seg.origin.iata_code,
|
|
185
|
+
destination: seg.destination.iata_code,
|
|
186
|
+
departingAt: seg.departing_at,
|
|
187
|
+
arrivingAt: seg.arriving_at,
|
|
188
|
+
carrierIataCode: seg.operating_carrier.iata_code,
|
|
189
|
+
flightNumber: seg.flight_number ?? "",
|
|
190
|
+
duration: seg.duration
|
|
191
|
+
}))
|
|
192
|
+
}));
|
|
193
|
+
const passengers = raw.passengers.map((passenger, index) => ({
|
|
194
|
+
id: passenger.id?.trim() || `passenger_${index}`,
|
|
195
|
+
type: passenger.type?.trim() || "adult",
|
|
196
|
+
givenName: passenger.given_name?.trim() || null,
|
|
197
|
+
familyName: passenger.family_name?.trim() || null
|
|
198
|
+
}));
|
|
199
|
+
const paymentRequirements = raw.payment_requirements ? {
|
|
200
|
+
requiresInstantPayment: raw.payment_requirements.requires_instant_payment !== false,
|
|
201
|
+
priceGuaranteeExpiresAt: raw.payment_requirements.price_guarantee_expires_at ?? null,
|
|
202
|
+
paymentRequiredBy: raw.payment_requirements.payment_required_by ?? null
|
|
203
|
+
} : null;
|
|
204
|
+
return {
|
|
205
|
+
id: raw.id,
|
|
206
|
+
totalAmount: raw.total_amount,
|
|
207
|
+
totalCurrency: raw.total_currency,
|
|
208
|
+
passengerCount: passengers.length > 0 ? passengers.length : 1,
|
|
209
|
+
slices,
|
|
210
|
+
expiresAt: raw.expires_at,
|
|
211
|
+
cabinClass,
|
|
212
|
+
passengers,
|
|
213
|
+
paymentRequirements
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
function mapOrder(raw) {
|
|
217
|
+
return {
|
|
218
|
+
id: raw.id,
|
|
219
|
+
bookingReference: raw.booking_reference ?? null,
|
|
220
|
+
totalAmount: raw.total_amount,
|
|
221
|
+
totalCurrency: raw.total_currency,
|
|
222
|
+
slices: raw.slices.map((slice) => ({
|
|
223
|
+
origin: slice.origin.iata_code,
|
|
224
|
+
destination: slice.destination.iata_code,
|
|
225
|
+
duration: slice.duration,
|
|
226
|
+
segments: slice.segments.map((segment) => ({
|
|
227
|
+
origin: segment.origin.iata_code,
|
|
228
|
+
destination: segment.destination.iata_code,
|
|
229
|
+
departingAt: segment.departing_at,
|
|
230
|
+
arrivingAt: segment.arriving_at,
|
|
231
|
+
carrierIataCode: segment.operating_carrier.iata_code,
|
|
232
|
+
flightNumber: segment.flight_number ?? "",
|
|
233
|
+
duration: segment.duration
|
|
234
|
+
}))
|
|
235
|
+
})),
|
|
236
|
+
passengers: raw.passengers.map((passenger, index) => ({
|
|
237
|
+
id: passenger.id?.trim() || `passenger_${index}`,
|
|
238
|
+
givenName: passenger.given_name?.trim() || null,
|
|
239
|
+
familyName: passenger.family_name?.trim() || null
|
|
240
|
+
})),
|
|
241
|
+
paymentStatus: raw.payment_status ? {
|
|
242
|
+
awaitingPayment: raw.payment_status.awaiting_payment === true,
|
|
243
|
+
paymentRequiredBy: raw.payment_status.payment_required_by ?? null,
|
|
244
|
+
priceGuaranteeExpiresAt: raw.payment_status.price_guarantee_expires_at ?? null
|
|
245
|
+
} : null,
|
|
246
|
+
documents: (raw.documents ?? []).map((document) => ({
|
|
247
|
+
type: document.type ?? null,
|
|
248
|
+
uniqueIdentifier: document.unique_identifier ?? null
|
|
249
|
+
}))
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
function mapPayment(raw) {
|
|
253
|
+
return {
|
|
254
|
+
id: raw.id,
|
|
255
|
+
orderId: raw.order_id,
|
|
256
|
+
status: raw.status,
|
|
257
|
+
currency: raw.currency,
|
|
258
|
+
amount: raw.amount,
|
|
259
|
+
type: raw.type,
|
|
260
|
+
failureReason: raw.failure_reason ?? null,
|
|
261
|
+
createdAt: raw.created_at ?? null
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
function readRelayCost(envelope) {
|
|
265
|
+
if (envelope === null || typeof envelope !== "object" || !("_meta" in envelope)) {
|
|
266
|
+
throw new Error("Duffel cloud relay response missing _meta envelope. Update Eliza Cloud or set ELIZA_DUFFEL_DIRECT=1.");
|
|
267
|
+
}
|
|
268
|
+
const meta = envelope._meta;
|
|
269
|
+
const cost = meta?.cost;
|
|
270
|
+
if (!cost || typeof cost.total_usd !== "number" || typeof cost.creator_markup_usd !== "number" || typeof cost.platform_fee_usd !== "number") {
|
|
271
|
+
throw new Error("Duffel cloud relay returned malformed _meta.cost. Refusing to proceed without billing receipt.");
|
|
272
|
+
}
|
|
273
|
+
const totalUsd = cost.total_usd;
|
|
274
|
+
const platformFeeUsd = cost.platform_fee_usd;
|
|
275
|
+
const markupPercent = totalUsd > 0 ? platformFeeUsd / totalUsd : null;
|
|
276
|
+
return {
|
|
277
|
+
totalUsd,
|
|
278
|
+
creatorMarkupUsd: cost.creator_markup_usd,
|
|
279
|
+
platformFeeUsd,
|
|
280
|
+
markupPercent,
|
|
281
|
+
metered: true
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
async function duffelFetch(args) {
|
|
285
|
+
const { config, method, directPath, cloudRelayPath, body, operation } = args;
|
|
286
|
+
const isCloud = config.mode === "cloud";
|
|
287
|
+
const url = isCloud ? `${config.cloudRelayBaseUrl ?? ""}${cloudRelayPath}` : `${getDuffelApiBase()}${directPath}`;
|
|
288
|
+
const headers = isCloud ? { "Content-Type": "application/json", Accept: "application/json" } : buildHeaders(config.apiKey ?? "");
|
|
289
|
+
const span = NOOP_DUFFEL_SPAN;
|
|
290
|
+
let response;
|
|
291
|
+
try {
|
|
292
|
+
response = await fetch(url, {
|
|
293
|
+
method,
|
|
294
|
+
headers,
|
|
295
|
+
body: body !== undefined ? JSON.stringify(body) : undefined,
|
|
296
|
+
signal: AbortSignal.timeout(30000)
|
|
297
|
+
});
|
|
298
|
+
} catch (error) {
|
|
299
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
300
|
+
logger2.error({
|
|
301
|
+
boundary: "elizacloud",
|
|
302
|
+
integration: "duffel",
|
|
303
|
+
operation,
|
|
304
|
+
mode: config.mode,
|
|
305
|
+
err: error instanceof Error ? error : undefined
|
|
306
|
+
}, `[elizacloud-duffel] Duffel ${operation} network error: ${msg}`);
|
|
307
|
+
span.failure({ error, errorKind: "network_error" });
|
|
308
|
+
throw new Error(`Duffel ${operation} failed: ${msg}`);
|
|
309
|
+
}
|
|
310
|
+
if (response.status === 402 && isCloud) {
|
|
311
|
+
const requirements = await parseX402Response(response);
|
|
312
|
+
logger2.warn({
|
|
313
|
+
boundary: "elizacloud",
|
|
314
|
+
integration: "duffel",
|
|
315
|
+
operation,
|
|
316
|
+
mode: config.mode,
|
|
317
|
+
statusCode: 402,
|
|
318
|
+
requirementCount: requirements?.length ?? 0
|
|
319
|
+
}, `[elizacloud-duffel] Duffel ${operation} returned 402 payment-required`);
|
|
320
|
+
span.failure({ statusCode: 402, errorKind: "payment_required" });
|
|
321
|
+
if (!requirements || requirements.length === 0) {
|
|
322
|
+
throw new PaymentRequiredError([], `Duffel ${operation} requires payment but the upstream did not advertise any payment options.`);
|
|
323
|
+
}
|
|
324
|
+
throw new PaymentRequiredError(requirements);
|
|
325
|
+
}
|
|
326
|
+
if (!response.ok) {
|
|
327
|
+
const errorBody = await response.text().catch(() => "");
|
|
328
|
+
const errorMsg = errorBody || `HTTP ${response.status}`;
|
|
329
|
+
logger2.warn({
|
|
330
|
+
boundary: "elizacloud",
|
|
331
|
+
integration: "duffel",
|
|
332
|
+
operation,
|
|
333
|
+
mode: config.mode,
|
|
334
|
+
statusCode: response.status
|
|
335
|
+
}, `[elizacloud-duffel] Duffel ${operation} HTTP error: ${errorMsg}`);
|
|
336
|
+
span.failure({ statusCode: response.status, errorKind: "http_error" });
|
|
337
|
+
throw new Error(`Duffel ${operation} failed (${response.status}): ${errorMsg}`);
|
|
338
|
+
}
|
|
339
|
+
const payload = await response.json();
|
|
340
|
+
span.success({ statusCode: response.status });
|
|
341
|
+
const cost = isCloud ? readRelayCost(payload) : DIRECT_MODE_COST;
|
|
342
|
+
return { data: payload, cost };
|
|
343
|
+
}
|
|
344
|
+
async function searchFlights(request, config) {
|
|
345
|
+
const resolvedConfig = config ?? readDuffelConfigFromEnv();
|
|
346
|
+
const passengerCount = Math.max(1, Math.round(request.passengers ?? 1));
|
|
347
|
+
const slices = [
|
|
348
|
+
{
|
|
349
|
+
origin: request.origin.toUpperCase().trim(),
|
|
350
|
+
destination: request.destination.toUpperCase().trim(),
|
|
351
|
+
departure_date: request.departureDate
|
|
352
|
+
}
|
|
353
|
+
];
|
|
354
|
+
if (request.returnDate) {
|
|
355
|
+
slices.push({
|
|
356
|
+
origin: request.destination.toUpperCase().trim(),
|
|
357
|
+
destination: request.origin.toUpperCase().trim(),
|
|
358
|
+
departure_date: request.returnDate
|
|
359
|
+
});
|
|
360
|
+
}
|
|
361
|
+
const requestBody = {
|
|
362
|
+
data: {
|
|
363
|
+
slices,
|
|
364
|
+
passengers: Array.from({ length: passengerCount }, () => ({
|
|
365
|
+
type: "adult"
|
|
366
|
+
})),
|
|
367
|
+
cabin_class: "economy"
|
|
368
|
+
}
|
|
369
|
+
};
|
|
370
|
+
logger2.info({
|
|
371
|
+
boundary: "elizacloud",
|
|
372
|
+
integration: "duffel",
|
|
373
|
+
origin: request.origin,
|
|
374
|
+
destination: request.destination
|
|
375
|
+
}, `[elizacloud-duffel] Searching flights ${request.origin} → ${request.destination} on ${request.departureDate}`);
|
|
376
|
+
const { data: responseData, cost } = await duffelFetch({
|
|
377
|
+
config: resolvedConfig,
|
|
378
|
+
method: "POST",
|
|
379
|
+
directPath: "/air/offer_requests?return_offers=true",
|
|
380
|
+
cloudRelayPath: "/api/cloud/travel-providers/duffel/offer-requests",
|
|
381
|
+
body: requestBody,
|
|
382
|
+
operation: "offer_request"
|
|
383
|
+
});
|
|
384
|
+
const offers = responseData.data.offers.map(mapOffer);
|
|
385
|
+
logger2.info({
|
|
386
|
+
boundary: "elizacloud",
|
|
387
|
+
integration: "duffel",
|
|
388
|
+
offerRequestId: responseData.data.id,
|
|
389
|
+
offerCount: offers.length,
|
|
390
|
+
costUsd: cost.totalUsd
|
|
391
|
+
}, `[elizacloud-duffel] Duffel returned ${offers.length} offers for request ${responseData.data.id}`);
|
|
392
|
+
return {
|
|
393
|
+
offerRequestId: responseData.data.id,
|
|
394
|
+
offers,
|
|
395
|
+
cost
|
|
396
|
+
};
|
|
397
|
+
}
|
|
398
|
+
async function getOffer(id, config) {
|
|
399
|
+
const resolvedConfig = config ?? readDuffelConfigFromEnv();
|
|
400
|
+
if (!id || id.trim().length === 0) {
|
|
401
|
+
throw new Error("Duffel getOffer: offer id is required");
|
|
402
|
+
}
|
|
403
|
+
const { data: responseData } = await duffelFetch({
|
|
404
|
+
config: resolvedConfig,
|
|
405
|
+
method: "GET",
|
|
406
|
+
directPath: `/air/offers/${encodeURIComponent(id.trim())}`,
|
|
407
|
+
cloudRelayPath: `/api/cloud/travel-providers/duffel/offers/${encodeURIComponent(id.trim())}`,
|
|
408
|
+
operation: "offer_retrieve"
|
|
409
|
+
});
|
|
410
|
+
return mapOffer(responseData.data);
|
|
411
|
+
}
|
|
412
|
+
async function createOrder(request, config) {
|
|
413
|
+
const resolvedConfig = config ?? readDuffelConfigFromEnv();
|
|
414
|
+
if (request.selectedOffers.length !== 1) {
|
|
415
|
+
throw new Error("Duffel createOrder: exactly one selected offer is required");
|
|
416
|
+
}
|
|
417
|
+
if (request.passengers.length === 0) {
|
|
418
|
+
throw new Error("Duffel createOrder: at least one passenger is required");
|
|
419
|
+
}
|
|
420
|
+
const data = {
|
|
421
|
+
type: request.type,
|
|
422
|
+
selected_offers: [...request.selectedOffers],
|
|
423
|
+
passengers: request.passengers.map((passenger) => ({
|
|
424
|
+
id: passenger.id,
|
|
425
|
+
title: passenger.title,
|
|
426
|
+
gender: passenger.gender,
|
|
427
|
+
given_name: passenger.givenName,
|
|
428
|
+
family_name: passenger.familyName,
|
|
429
|
+
born_on: passenger.bornOn,
|
|
430
|
+
email: passenger.email,
|
|
431
|
+
phone_number: passenger.phoneNumber
|
|
432
|
+
}))
|
|
433
|
+
};
|
|
434
|
+
if (request.payment) {
|
|
435
|
+
data.payments = [
|
|
436
|
+
{
|
|
437
|
+
type: request.payment.type,
|
|
438
|
+
amount: request.payment.amount,
|
|
439
|
+
currency: request.payment.currency
|
|
440
|
+
}
|
|
441
|
+
];
|
|
442
|
+
}
|
|
443
|
+
if (request.metadata && Object.keys(request.metadata).length > 0) {
|
|
444
|
+
data.metadata = request.metadata;
|
|
445
|
+
}
|
|
446
|
+
const { data: response } = await duffelFetch({
|
|
447
|
+
config: resolvedConfig,
|
|
448
|
+
method: "POST",
|
|
449
|
+
directPath: "/air/orders",
|
|
450
|
+
cloudRelayPath: "/api/cloud/travel-providers/duffel/orders",
|
|
451
|
+
body: { data },
|
|
452
|
+
operation: "order_create"
|
|
453
|
+
});
|
|
454
|
+
return mapOrder(response.data);
|
|
455
|
+
}
|
|
456
|
+
async function getOrder(orderId, config) {
|
|
457
|
+
const resolvedConfig = config ?? readDuffelConfigFromEnv();
|
|
458
|
+
if (!orderId || orderId.trim().length === 0) {
|
|
459
|
+
throw new Error("Duffel getOrder: order id is required");
|
|
460
|
+
}
|
|
461
|
+
const { data: response } = await duffelFetch({
|
|
462
|
+
config: resolvedConfig,
|
|
463
|
+
method: "GET",
|
|
464
|
+
directPath: `/air/orders/${encodeURIComponent(orderId.trim())}`,
|
|
465
|
+
cloudRelayPath: `/api/cloud/travel-providers/duffel/orders/${encodeURIComponent(orderId.trim())}`,
|
|
466
|
+
operation: "order_retrieve"
|
|
467
|
+
});
|
|
468
|
+
return mapOrder(response.data);
|
|
469
|
+
}
|
|
470
|
+
async function createPayment(args, config) {
|
|
471
|
+
const resolvedConfig = config ?? readDuffelConfigFromEnv();
|
|
472
|
+
if (args.orderId.trim().length === 0) {
|
|
473
|
+
throw new Error("Duffel createPayment: order id is required");
|
|
474
|
+
}
|
|
475
|
+
if (args.amount.trim().length === 0) {
|
|
476
|
+
throw new Error("Duffel createPayment: amount is required");
|
|
477
|
+
}
|
|
478
|
+
if (args.currency.trim().length === 0) {
|
|
479
|
+
throw new Error("Duffel createPayment: currency is required");
|
|
480
|
+
}
|
|
481
|
+
const { data: response } = await duffelFetch({
|
|
482
|
+
config: resolvedConfig,
|
|
483
|
+
method: "POST",
|
|
484
|
+
directPath: "/air/payments",
|
|
485
|
+
cloudRelayPath: "/api/cloud/travel-providers/duffel/payments",
|
|
486
|
+
body: {
|
|
487
|
+
data: {
|
|
488
|
+
order_id: args.orderId.trim(),
|
|
489
|
+
payment: {
|
|
490
|
+
type: "balance",
|
|
491
|
+
amount: args.amount.trim(),
|
|
492
|
+
currency: args.currency.trim().toUpperCase()
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
},
|
|
496
|
+
operation: "payment_create"
|
|
497
|
+
});
|
|
498
|
+
return mapPayment(response.data);
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
// src/cloud/lifeops-schedule-sync-client.ts
|
|
502
|
+
init_base_url();
|
|
503
|
+
var LIFEOPS_SCHEDULE_REQUEST_TIMEOUT_MS = 20000;
|
|
504
|
+
|
|
505
|
+
class LifeOpsScheduleSyncClientError extends Error {
|
|
506
|
+
status;
|
|
507
|
+
constructor(status, message) {
|
|
508
|
+
super(message);
|
|
509
|
+
this.status = status;
|
|
510
|
+
this.name = "LifeOpsScheduleSyncClientError";
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
function normalizeOptionalString(value) {
|
|
514
|
+
const trimmed = value?.trim();
|
|
515
|
+
return trimmed && trimmed.length > 0 ? trimmed : null;
|
|
516
|
+
}
|
|
517
|
+
function normalizeLifeOpsScheduleSyncSecret(value) {
|
|
518
|
+
const trimmed = normalizeOptionalString(value);
|
|
519
|
+
if (!trimmed) {
|
|
520
|
+
return null;
|
|
521
|
+
}
|
|
522
|
+
return trimmed.toUpperCase() === "[REDACTED]" ? null : trimmed;
|
|
523
|
+
}
|
|
524
|
+
function resolveLifeOpsScheduleSyncConfig(config = {}) {
|
|
525
|
+
const remoteApiBase = normalizeOptionalString(config.remoteApiBase);
|
|
526
|
+
if (remoteApiBase) {
|
|
527
|
+
return {
|
|
528
|
+
configured: true,
|
|
529
|
+
mode: "remote",
|
|
530
|
+
baseUrl: remoteApiBase.replace(/\/+$/, ""),
|
|
531
|
+
accessToken: normalizeLifeOpsScheduleSyncSecret(config.remoteAccessToken) ?? normalizeLifeOpsScheduleSyncSecret(process.env.ELIZA_REMOTE_ACCESS_TOKEN)
|
|
532
|
+
};
|
|
533
|
+
}
|
|
534
|
+
const apiKey = normalizeLifeOpsScheduleSyncSecret(config.apiKey) ?? normalizeLifeOpsScheduleSyncSecret(process.env.ELIZAOS_CLOUD_API_KEY);
|
|
535
|
+
const agentId = normalizeLifeOpsScheduleSyncSecret(config.agentId) ?? normalizeLifeOpsScheduleSyncSecret(process.env.ELIZAOS_CLOUD_AGENT_ID);
|
|
536
|
+
if (!apiKey || !agentId) {
|
|
537
|
+
return {
|
|
538
|
+
configured: false,
|
|
539
|
+
mode: "none"
|
|
540
|
+
};
|
|
541
|
+
}
|
|
542
|
+
return {
|
|
543
|
+
configured: true,
|
|
544
|
+
mode: "cloud",
|
|
545
|
+
apiBaseUrl: resolveCloudApiBaseUrl(normalizeOptionalString(config.baseUrl) ?? process.env.ELIZAOS_CLOUD_BASE_URL),
|
|
546
|
+
apiKey,
|
|
547
|
+
agentId
|
|
548
|
+
};
|
|
549
|
+
}
|
|
550
|
+
function buildTimeoutSignal() {
|
|
551
|
+
return AbortSignal.timeout(LIFEOPS_SCHEDULE_REQUEST_TIMEOUT_MS);
|
|
552
|
+
}
|
|
553
|
+
async function readJsonResponse(response) {
|
|
554
|
+
if (!response.ok) {
|
|
555
|
+
let detail = `${response.status} ${response.statusText}`.trim();
|
|
556
|
+
const text = await response.text();
|
|
557
|
+
const trimmed = text.trim();
|
|
558
|
+
if (trimmed.length > 0) {
|
|
559
|
+
try {
|
|
560
|
+
const parsed = JSON.parse(trimmed);
|
|
561
|
+
detail = parsed.message ?? parsed.error ?? trimmed;
|
|
562
|
+
} catch {
|
|
563
|
+
detail = trimmed.slice(0, 200);
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
throw new LifeOpsScheduleSyncClientError(response.status, detail);
|
|
567
|
+
}
|
|
568
|
+
return await response.json();
|
|
569
|
+
}
|
|
570
|
+
function resolveLifeOpsScheduleSyncSiteUrl(rawUrl) {
|
|
571
|
+
return normalizeCloudSiteUrl(rawUrl);
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
class LifeOpsScheduleSyncClient {
|
|
575
|
+
configSource;
|
|
576
|
+
constructor(configSource = resolveLifeOpsScheduleSyncConfig) {
|
|
577
|
+
this.configSource = configSource;
|
|
578
|
+
}
|
|
579
|
+
getConfig() {
|
|
580
|
+
return typeof this.configSource === "function" ? this.configSource() : this.configSource;
|
|
581
|
+
}
|
|
582
|
+
get configured() {
|
|
583
|
+
return this.getConfig().configured;
|
|
584
|
+
}
|
|
585
|
+
requireConfig() {
|
|
586
|
+
const config = this.getConfig();
|
|
587
|
+
if (!config.configured) {
|
|
588
|
+
throw new LifeOpsScheduleSyncClientError(409, "LifeOps schedule sync is not configured.");
|
|
589
|
+
}
|
|
590
|
+
return config;
|
|
591
|
+
}
|
|
592
|
+
resolvePath(pathname) {
|
|
593
|
+
const config = this.requireConfig();
|
|
594
|
+
const normalizedPath = pathname.replace(/^\/+/, "");
|
|
595
|
+
if (config.mode === "remote") {
|
|
596
|
+
return new URL(`api/lifeops/schedule/${normalizedPath}`, `${config.baseUrl.replace(/\/+$/, "")}/`).toString();
|
|
597
|
+
}
|
|
598
|
+
return new URL(`eliza/agents/${encodeURIComponent(config.agentId)}/lifeops/schedule/${normalizedPath}`, `${config.apiBaseUrl.replace(/\/+$/, "")}/`).toString();
|
|
599
|
+
}
|
|
600
|
+
requestHeaders(initHeaders) {
|
|
601
|
+
const config = this.requireConfig();
|
|
602
|
+
const headers = {
|
|
603
|
+
Accept: "application/json",
|
|
604
|
+
"Content-Type": "application/json"
|
|
605
|
+
};
|
|
606
|
+
if (config.mode === "cloud") {
|
|
607
|
+
headers["X-API-Key"] = config.apiKey;
|
|
608
|
+
}
|
|
609
|
+
if (config.mode === "remote" && config.accessToken) {
|
|
610
|
+
headers.Authorization = `Bearer ${config.accessToken}`;
|
|
611
|
+
}
|
|
612
|
+
if (initHeaders instanceof Headers) {
|
|
613
|
+
for (const [key, value] of initHeaders.entries()) {
|
|
614
|
+
headers[key] = value;
|
|
615
|
+
}
|
|
616
|
+
return headers;
|
|
617
|
+
}
|
|
618
|
+
if (Array.isArray(initHeaders)) {
|
|
619
|
+
for (const [key, value] of initHeaders) {
|
|
620
|
+
headers[key] = value;
|
|
621
|
+
}
|
|
622
|
+
return headers;
|
|
623
|
+
}
|
|
624
|
+
return {
|
|
625
|
+
...headers,
|
|
626
|
+
...initHeaders ?? {}
|
|
627
|
+
};
|
|
628
|
+
}
|
|
629
|
+
async request(pathname, init) {
|
|
630
|
+
const response = await fetch(this.resolvePath(pathname), {
|
|
631
|
+
...init,
|
|
632
|
+
headers: this.requestHeaders(init.headers),
|
|
633
|
+
signal: init.signal ?? buildTimeoutSignal()
|
|
634
|
+
});
|
|
635
|
+
return readJsonResponse(response);
|
|
636
|
+
}
|
|
637
|
+
async syncObservations(request) {
|
|
638
|
+
return this.request("observations", {
|
|
639
|
+
method: "POST",
|
|
640
|
+
body: JSON.stringify(request)
|
|
641
|
+
});
|
|
642
|
+
}
|
|
643
|
+
async getMergedState(timezone, scope = "cloud") {
|
|
644
|
+
const query = new URLSearchParams({ timezone, scope });
|
|
645
|
+
return this.request(`merged-state?${query.toString()}`, {
|
|
646
|
+
method: "GET"
|
|
647
|
+
});
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
// src/cloud/lifeops-schedule-sync-contracts.ts
|
|
652
|
+
var LIFEOPS_SCHEDULE_DEVICE_KINDS = [
|
|
653
|
+
"iphone",
|
|
654
|
+
"ipad",
|
|
655
|
+
"mac",
|
|
656
|
+
"watch",
|
|
657
|
+
"cloud",
|
|
658
|
+
"unknown"
|
|
659
|
+
];
|
|
660
|
+
var LIFEOPS_SCHEDULE_OBSERVATION_ORIGINS = [
|
|
661
|
+
"local_inference",
|
|
662
|
+
"device_sync"
|
|
663
|
+
];
|
|
664
|
+
var LIFEOPS_SCHEDULE_STATE_SCOPES = ["local", "cloud"];
|
|
665
|
+
|
|
666
|
+
// src/cloud/managed-payment-clients.ts
|
|
667
|
+
init_base_url();
|
|
668
|
+
init_base_url();
|
|
669
|
+
function normalizeElizaCloudApiKey(value) {
|
|
670
|
+
const trimmed = value?.trim();
|
|
671
|
+
if (!trimmed)
|
|
672
|
+
return null;
|
|
673
|
+
return trimmed.toUpperCase() === "[REDACTED]" ? null : trimmed;
|
|
674
|
+
}
|
|
675
|
+
function resolveEnvElizaCloudManagedClientConfig(env = typeof process === "undefined" ? {} : process.env) {
|
|
676
|
+
const apiKey = normalizeElizaCloudApiKey(env.ELIZAOS_CLOUD_API_KEY);
|
|
677
|
+
const baseUrl = env.ELIZAOS_CLOUD_BASE_URL;
|
|
678
|
+
return {
|
|
679
|
+
configured: Boolean(apiKey),
|
|
680
|
+
apiKey,
|
|
681
|
+
apiBaseUrl: resolveCloudApiBaseUrl(baseUrl),
|
|
682
|
+
siteUrl: normalizeCloudSiteUrl(baseUrl)
|
|
683
|
+
};
|
|
684
|
+
}
|
|
685
|
+
var PLAID_REQUEST_TIMEOUT_MS = 30000;
|
|
686
|
+
var PAYPAL_REQUEST_TIMEOUT_MS = 30000;
|
|
687
|
+
|
|
688
|
+
class PlaidManagedClientError extends Error {
|
|
689
|
+
status;
|
|
690
|
+
constructor(status, message) {
|
|
691
|
+
super(message);
|
|
692
|
+
this.status = status;
|
|
693
|
+
this.name = "PlaidManagedClientError";
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
class PaypalManagedClientError extends Error {
|
|
698
|
+
status;
|
|
699
|
+
fallback;
|
|
700
|
+
constructor(status, message, fallback = null) {
|
|
701
|
+
super(message);
|
|
702
|
+
this.status = status;
|
|
703
|
+
this.fallback = fallback;
|
|
704
|
+
this.name = "PaypalManagedClientError";
|
|
705
|
+
}
|
|
706
|
+
}
|
|
707
|
+
async function readPlaidJson(response) {
|
|
708
|
+
if (!response.ok) {
|
|
709
|
+
let detail = `${response.status} ${response.statusText}`.trim();
|
|
710
|
+
const text = await response.text();
|
|
711
|
+
if (text.trim().length > 0) {
|
|
712
|
+
try {
|
|
713
|
+
const parsed = JSON.parse(text);
|
|
714
|
+
detail = parsed.message ?? parsed.error ?? text.slice(0, 240);
|
|
715
|
+
} catch {
|
|
716
|
+
detail = text.slice(0, 240);
|
|
717
|
+
}
|
|
718
|
+
}
|
|
719
|
+
throw new PlaidManagedClientError(response.status, detail);
|
|
720
|
+
}
|
|
721
|
+
return await response.json();
|
|
722
|
+
}
|
|
723
|
+
async function readPaypalJson(response) {
|
|
724
|
+
if (!response.ok) {
|
|
725
|
+
let detail = `${response.status} ${response.statusText}`.trim();
|
|
726
|
+
let fallback = null;
|
|
727
|
+
const text = await response.text();
|
|
728
|
+
if (text.trim().length > 0) {
|
|
729
|
+
try {
|
|
730
|
+
const parsed = JSON.parse(text);
|
|
731
|
+
detail = parsed.message ?? parsed.error ?? text.slice(0, 240);
|
|
732
|
+
fallback = parsed.fallback ?? null;
|
|
733
|
+
} catch {
|
|
734
|
+
detail = text.slice(0, 240);
|
|
735
|
+
}
|
|
736
|
+
}
|
|
737
|
+
throw new PaypalManagedClientError(response.status, detail, fallback);
|
|
738
|
+
}
|
|
739
|
+
return await response.json();
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
class PlaidManagedClient {
|
|
743
|
+
configSource;
|
|
744
|
+
constructor(configSource = resolveEnvElizaCloudManagedClientConfig) {
|
|
745
|
+
this.configSource = configSource;
|
|
746
|
+
}
|
|
747
|
+
requireConfig() {
|
|
748
|
+
const config = this.configSource();
|
|
749
|
+
if (!config.apiKey) {
|
|
750
|
+
throw new PlaidManagedClientError(409, "Eliza Cloud is not connected.");
|
|
751
|
+
}
|
|
752
|
+
return { ...config, apiKey: config.apiKey };
|
|
753
|
+
}
|
|
754
|
+
get configured() {
|
|
755
|
+
return this.configSource().configured;
|
|
756
|
+
}
|
|
757
|
+
async createLinkToken() {
|
|
758
|
+
const config = this.requireConfig();
|
|
759
|
+
const response = await fetch(`${config.apiBaseUrl}/v1/eliza/plaid/link-token`, {
|
|
760
|
+
method: "POST",
|
|
761
|
+
headers: {
|
|
762
|
+
Authorization: `Bearer ${config.apiKey}`,
|
|
763
|
+
"Content-Type": "application/json"
|
|
764
|
+
},
|
|
765
|
+
body: "{}",
|
|
766
|
+
signal: AbortSignal.timeout(PLAID_REQUEST_TIMEOUT_MS)
|
|
767
|
+
});
|
|
768
|
+
return readPlaidJson(response);
|
|
769
|
+
}
|
|
770
|
+
async exchangePublicToken(args) {
|
|
771
|
+
const config = this.requireConfig();
|
|
772
|
+
const response = await fetch(`${config.apiBaseUrl}/v1/eliza/plaid/exchange`, {
|
|
773
|
+
method: "POST",
|
|
774
|
+
headers: {
|
|
775
|
+
Authorization: `Bearer ${config.apiKey}`,
|
|
776
|
+
"Content-Type": "application/json"
|
|
777
|
+
},
|
|
778
|
+
body: JSON.stringify({ publicToken: args.publicToken }),
|
|
779
|
+
signal: AbortSignal.timeout(PLAID_REQUEST_TIMEOUT_MS)
|
|
780
|
+
});
|
|
781
|
+
return readPlaidJson(response);
|
|
782
|
+
}
|
|
783
|
+
async syncTransactions(args) {
|
|
784
|
+
const config = this.requireConfig();
|
|
785
|
+
const response = await fetch(`${config.apiBaseUrl}/v1/eliza/plaid/sync`, {
|
|
786
|
+
method: "POST",
|
|
787
|
+
headers: {
|
|
788
|
+
Authorization: `Bearer ${config.apiKey}`,
|
|
789
|
+
"Content-Type": "application/json"
|
|
790
|
+
},
|
|
791
|
+
body: JSON.stringify({
|
|
792
|
+
accessToken: args.accessToken,
|
|
793
|
+
cursor: args.cursor ?? "",
|
|
794
|
+
count: args.count ?? 250
|
|
795
|
+
}),
|
|
796
|
+
signal: AbortSignal.timeout(PLAID_REQUEST_TIMEOUT_MS * 2)
|
|
797
|
+
});
|
|
798
|
+
return readPlaidJson(response);
|
|
799
|
+
}
|
|
800
|
+
}
|
|
801
|
+
|
|
802
|
+
class PaypalManagedClient {
|
|
803
|
+
configSource;
|
|
804
|
+
constructor(configSource = resolveEnvElizaCloudManagedClientConfig) {
|
|
805
|
+
this.configSource = configSource;
|
|
806
|
+
}
|
|
807
|
+
requireConfig() {
|
|
808
|
+
const config = this.configSource();
|
|
809
|
+
if (!config.apiKey) {
|
|
810
|
+
throw new PaypalManagedClientError(409, "Eliza Cloud is not connected.");
|
|
811
|
+
}
|
|
812
|
+
return { ...config, apiKey: config.apiKey };
|
|
813
|
+
}
|
|
814
|
+
get configured() {
|
|
815
|
+
return this.configSource().configured;
|
|
816
|
+
}
|
|
817
|
+
async buildAuthorizeUrl(args) {
|
|
818
|
+
const config = this.requireConfig();
|
|
819
|
+
const response = await fetch(`${config.apiBaseUrl}/v1/eliza/paypal/authorize`, {
|
|
820
|
+
method: "POST",
|
|
821
|
+
headers: {
|
|
822
|
+
Authorization: `Bearer ${config.apiKey}`,
|
|
823
|
+
"Content-Type": "application/json"
|
|
824
|
+
},
|
|
825
|
+
body: JSON.stringify({ state: args.state }),
|
|
826
|
+
signal: AbortSignal.timeout(PAYPAL_REQUEST_TIMEOUT_MS)
|
|
827
|
+
});
|
|
828
|
+
return readPaypalJson(response);
|
|
829
|
+
}
|
|
830
|
+
async exchangeCode(args) {
|
|
831
|
+
const config = this.requireConfig();
|
|
832
|
+
const response = await fetch(`${config.apiBaseUrl}/v1/eliza/paypal/callback`, {
|
|
833
|
+
method: "POST",
|
|
834
|
+
headers: {
|
|
835
|
+
Authorization: `Bearer ${config.apiKey}`,
|
|
836
|
+
"Content-Type": "application/json"
|
|
837
|
+
},
|
|
838
|
+
body: JSON.stringify({ code: args.code }),
|
|
839
|
+
signal: AbortSignal.timeout(PAYPAL_REQUEST_TIMEOUT_MS)
|
|
840
|
+
});
|
|
841
|
+
return readPaypalJson(response);
|
|
842
|
+
}
|
|
843
|
+
async refreshAccessToken(args) {
|
|
844
|
+
const config = this.requireConfig();
|
|
845
|
+
const response = await fetch(`${config.apiBaseUrl}/v1/eliza/paypal/refresh`, {
|
|
846
|
+
method: "POST",
|
|
847
|
+
headers: {
|
|
848
|
+
Authorization: `Bearer ${config.apiKey}`,
|
|
849
|
+
"Content-Type": "application/json"
|
|
850
|
+
},
|
|
851
|
+
body: JSON.stringify({ refreshToken: args.refreshToken }),
|
|
852
|
+
signal: AbortSignal.timeout(PAYPAL_REQUEST_TIMEOUT_MS)
|
|
853
|
+
});
|
|
854
|
+
return readPaypalJson(response);
|
|
855
|
+
}
|
|
856
|
+
async searchTransactions(args) {
|
|
857
|
+
const config = this.requireConfig();
|
|
858
|
+
const response = await fetch(`${config.apiBaseUrl}/v1/eliza/paypal/transactions`, {
|
|
859
|
+
method: "POST",
|
|
860
|
+
headers: {
|
|
861
|
+
Authorization: `Bearer ${config.apiKey}`,
|
|
862
|
+
"Content-Type": "application/json"
|
|
863
|
+
},
|
|
864
|
+
body: JSON.stringify(args),
|
|
865
|
+
signal: AbortSignal.timeout(PAYPAL_REQUEST_TIMEOUT_MS * 2)
|
|
866
|
+
});
|
|
867
|
+
return readPaypalJson(response);
|
|
868
|
+
}
|
|
869
|
+
}
|
|
18
870
|
export {
|
|
19
871
|
validateCloudBaseUrl,
|
|
20
|
-
|
|
21
|
-
|
|
872
|
+
searchFlights,
|
|
873
|
+
resolveLifeOpsScheduleSyncSiteUrl,
|
|
874
|
+
resolveLifeOpsScheduleSyncConfig,
|
|
875
|
+
resolveEnvElizaCloudManagedClientConfig,
|
|
876
|
+
resolveCloudApiBaseUrl2 as resolveCloudApiBaseUrl,
|
|
877
|
+
requestPayment,
|
|
878
|
+
readDuffelConfigFromEnv,
|
|
879
|
+
parseX402Response,
|
|
880
|
+
normalizeLifeOpsScheduleSyncSecret,
|
|
881
|
+
normalizeElizaCloudApiKey,
|
|
882
|
+
normalizeCloudSiteUrl2 as normalizeCloudSiteUrl,
|
|
883
|
+
normalizeCloudApiKey,
|
|
884
|
+
isCloudAuthApiKeyService,
|
|
885
|
+
getOrder,
|
|
886
|
+
getOffer,
|
|
887
|
+
createPayment,
|
|
888
|
+
createOrder,
|
|
22
889
|
cloudLogin,
|
|
890
|
+
PlaidManagedClientError,
|
|
891
|
+
PlaidManagedClient,
|
|
892
|
+
PaypalManagedClientError,
|
|
893
|
+
PaypalManagedClient,
|
|
894
|
+
PaymentRequiredError,
|
|
895
|
+
LifeOpsScheduleSyncClientError,
|
|
896
|
+
LifeOpsScheduleSyncClient,
|
|
897
|
+
LIFEOPS_SCHEDULE_STATE_SCOPES,
|
|
898
|
+
LIFEOPS_SCHEDULE_OBSERVATION_ORIGINS,
|
|
899
|
+
LIFEOPS_SCHEDULE_DEVICE_KINDS,
|
|
23
900
|
ElizaCloudClient,
|
|
901
|
+
DuffelConfigError,
|
|
24
902
|
ConnectionMonitor,
|
|
25
903
|
CloudRuntimeProxy,
|
|
26
904
|
CloudManager,
|
|
27
905
|
BackupScheduler
|
|
28
906
|
};
|
|
29
907
|
|
|
30
|
-
//# debugId=
|
|
908
|
+
//# debugId=DEF1FE9ADA582A9064756E2164756E21
|