@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
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
export declare class DuffelConfigError extends Error {
|
|
2
|
+
readonly code: "DUFFEL_NOT_CONFIGURED";
|
|
3
|
+
constructor(message: string);
|
|
4
|
+
}
|
|
5
|
+
/** Direct mode hits api.duffel.com with the user's own DUFFEL_API_KEY.
|
|
6
|
+
* Cloud mode hits the local Eliza Cloud relay which performs the upstream
|
|
7
|
+
* Duffel call, applies creator markup, and meters against the user's
|
|
8
|
+
* Cloud credit balance. Cloud mode is the default. */
|
|
9
|
+
export type DuffelMode = "cloud" | "direct";
|
|
10
|
+
export interface DuffelConfig {
|
|
11
|
+
mode: DuffelMode;
|
|
12
|
+
/** Required when mode === "direct". */
|
|
13
|
+
apiKey: string | null;
|
|
14
|
+
/** Required when mode === "cloud". Local Eliza agent API base, e.g.
|
|
15
|
+
* http://127.0.0.1:31337. The relay path is appended internally. */
|
|
16
|
+
cloudRelayBaseUrl: string | null;
|
|
17
|
+
}
|
|
18
|
+
export declare function readDuffelConfigFromEnv(env?: NodeJS.ProcessEnv): DuffelConfig;
|
|
19
|
+
export interface SearchFlightsRequest {
|
|
20
|
+
/** IATA airport code for origin, e.g. "JFK". */
|
|
21
|
+
origin: string;
|
|
22
|
+
/** IATA airport code for destination, e.g. "LHR". */
|
|
23
|
+
destination: string;
|
|
24
|
+
/** ISO 8601 date string (YYYY-MM-DD). */
|
|
25
|
+
departureDate: string;
|
|
26
|
+
/**
|
|
27
|
+
* ISO 8601 date string for return leg.
|
|
28
|
+
* Omit or pass undefined for one-way search.
|
|
29
|
+
*/
|
|
30
|
+
returnDate?: string;
|
|
31
|
+
/** Number of adult passengers (default 1). */
|
|
32
|
+
passengers?: number;
|
|
33
|
+
}
|
|
34
|
+
export interface DuffelSegment {
|
|
35
|
+
origin: string;
|
|
36
|
+
destination: string;
|
|
37
|
+
departingAt: string;
|
|
38
|
+
arrivingAt: string;
|
|
39
|
+
carrierIataCode: string;
|
|
40
|
+
flightNumber: string;
|
|
41
|
+
duration: string;
|
|
42
|
+
}
|
|
43
|
+
export interface DuffelSlice {
|
|
44
|
+
origin: string;
|
|
45
|
+
destination: string;
|
|
46
|
+
duration: string;
|
|
47
|
+
segments: DuffelSegment[];
|
|
48
|
+
}
|
|
49
|
+
export interface DuffelOfferPassenger {
|
|
50
|
+
id: string;
|
|
51
|
+
type: string;
|
|
52
|
+
givenName: string | null;
|
|
53
|
+
familyName: string | null;
|
|
54
|
+
}
|
|
55
|
+
export interface DuffelPaymentRequirements {
|
|
56
|
+
requiresInstantPayment: boolean;
|
|
57
|
+
priceGuaranteeExpiresAt: string | null;
|
|
58
|
+
paymentRequiredBy: string | null;
|
|
59
|
+
}
|
|
60
|
+
export interface DuffelOffer {
|
|
61
|
+
id: string;
|
|
62
|
+
totalAmount: string;
|
|
63
|
+
totalCurrency: string;
|
|
64
|
+
passengerCount: number;
|
|
65
|
+
slices: DuffelSlice[];
|
|
66
|
+
expiresAt: string | null;
|
|
67
|
+
/** Raw cabin class reported by Duffel for the first slice. */
|
|
68
|
+
cabinClass: string | null;
|
|
69
|
+
passengers: DuffelOfferPassenger[];
|
|
70
|
+
paymentRequirements: DuffelPaymentRequirements | null;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Cost envelope returned by the cloud relay. The breakdown is computed
|
|
74
|
+
* server-side (commandment 2 — no client-side math) and the local code
|
|
75
|
+
* forwards it to the UI for display. In direct mode all values are zero
|
|
76
|
+
* because no markup is charged.
|
|
77
|
+
*
|
|
78
|
+
* `markupPercent` is a *display-only* derived field: it equals
|
|
79
|
+
* `platformFeeUsd / totalUsd`, computed once at the boundary so UI
|
|
80
|
+
* components don't repeat the division. The pricing decision itself is
|
|
81
|
+
* still Cloud-side — this is the same pattern as a "discount %" badge
|
|
82
|
+
* derived from a server-supplied price.
|
|
83
|
+
*/
|
|
84
|
+
export interface DuffelCallCost {
|
|
85
|
+
/** Net cost charged to the user's Cloud credit balance, in USD. */
|
|
86
|
+
totalUsd: number;
|
|
87
|
+
/** Portion that flows to the creator as markup, in USD. */
|
|
88
|
+
creatorMarkupUsd: number;
|
|
89
|
+
/** Eliza Cloud platform fee portion, in USD. */
|
|
90
|
+
platformFeeUsd: number;
|
|
91
|
+
/** Display-only ratio of platform fee to total (e.g. 0.2 for 20%).
|
|
92
|
+
* Derived from server values, never used for pricing. Null when
|
|
93
|
+
* totalUsd is zero (direct mode or free call). */
|
|
94
|
+
markupPercent: number | null;
|
|
95
|
+
/** Whether the call was metered (true in cloud mode, false in direct mode). */
|
|
96
|
+
metered: boolean;
|
|
97
|
+
}
|
|
98
|
+
export interface SearchFlightsResult {
|
|
99
|
+
offerRequestId: string;
|
|
100
|
+
offers: DuffelOffer[];
|
|
101
|
+
cost: DuffelCallCost;
|
|
102
|
+
}
|
|
103
|
+
export interface DuffelOrderPassenger {
|
|
104
|
+
id: string;
|
|
105
|
+
givenName: string | null;
|
|
106
|
+
familyName: string | null;
|
|
107
|
+
}
|
|
108
|
+
export interface DuffelOrderPaymentStatus {
|
|
109
|
+
awaitingPayment: boolean;
|
|
110
|
+
paymentRequiredBy: string | null;
|
|
111
|
+
priceGuaranteeExpiresAt: string | null;
|
|
112
|
+
}
|
|
113
|
+
export interface DuffelOrderDocument {
|
|
114
|
+
type: string | null;
|
|
115
|
+
uniqueIdentifier: string | null;
|
|
116
|
+
}
|
|
117
|
+
export interface DuffelOrder {
|
|
118
|
+
id: string;
|
|
119
|
+
bookingReference: string | null;
|
|
120
|
+
totalAmount: string;
|
|
121
|
+
totalCurrency: string;
|
|
122
|
+
slices: DuffelSlice[];
|
|
123
|
+
passengers: DuffelOrderPassenger[];
|
|
124
|
+
paymentStatus: DuffelOrderPaymentStatus | null;
|
|
125
|
+
documents: DuffelOrderDocument[];
|
|
126
|
+
}
|
|
127
|
+
export interface DuffelPayment {
|
|
128
|
+
id: string;
|
|
129
|
+
orderId: string;
|
|
130
|
+
status: string;
|
|
131
|
+
currency: string;
|
|
132
|
+
amount: string;
|
|
133
|
+
type: string;
|
|
134
|
+
failureReason: string | null;
|
|
135
|
+
createdAt: string | null;
|
|
136
|
+
}
|
|
137
|
+
export interface DuffelOrderPassengerInput {
|
|
138
|
+
id: string;
|
|
139
|
+
title?: string;
|
|
140
|
+
gender?: string;
|
|
141
|
+
givenName: string;
|
|
142
|
+
familyName: string;
|
|
143
|
+
bornOn: string;
|
|
144
|
+
email?: string;
|
|
145
|
+
phoneNumber?: string;
|
|
146
|
+
}
|
|
147
|
+
export interface CreateDuffelOrderRequest {
|
|
148
|
+
selectedOffers: ReadonlyArray<string>;
|
|
149
|
+
passengers: ReadonlyArray<DuffelOrderPassengerInput>;
|
|
150
|
+
type: "hold" | "instant";
|
|
151
|
+
payment?: {
|
|
152
|
+
type: "balance";
|
|
153
|
+
amount: string;
|
|
154
|
+
currency: string;
|
|
155
|
+
};
|
|
156
|
+
metadata?: Readonly<Record<string, string>>;
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Search for available flight offers via the Duffel Offer Requests API.
|
|
160
|
+
*
|
|
161
|
+
* Throws `DuffelConfigError` when DUFFEL_API_KEY is absent.
|
|
162
|
+
* One-way search when `returnDate` is omitted; return search when provided.
|
|
163
|
+
*
|
|
164
|
+
*/
|
|
165
|
+
export declare function searchFlights(request: SearchFlightsRequest, config?: DuffelConfig): Promise<SearchFlightsResult>;
|
|
166
|
+
/**
|
|
167
|
+
* Retrieve a single flight offer by ID.
|
|
168
|
+
*
|
|
169
|
+
* Use after `searchFlights` to get live pricing and full details for a
|
|
170
|
+
* specific offer before presenting it to the user for approval.
|
|
171
|
+
*
|
|
172
|
+
*/
|
|
173
|
+
export declare function getOffer(id: string, config?: DuffelConfig): Promise<DuffelOffer>;
|
|
174
|
+
export declare function createOrder(request: CreateDuffelOrderRequest, config?: DuffelConfig): Promise<DuffelOrder>;
|
|
175
|
+
export declare function getOrder(orderId: string, config?: DuffelConfig): Promise<DuffelOrder>;
|
|
176
|
+
export declare function createPayment(args: {
|
|
177
|
+
orderId: string;
|
|
178
|
+
amount: string;
|
|
179
|
+
currency: string;
|
|
180
|
+
}, config?: DuffelConfig): Promise<DuffelPayment>;
|
|
181
|
+
//# sourceMappingURL=duffel-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"duffel-client.d.ts","sourceRoot":"","sources":["../../src/cloud/duffel-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,506 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __returnValue = (v) => v;
|
|
4
|
+
function __exportSetter(name, newValue) {
|
|
5
|
+
this[name] = __returnValue.bind(null, newValue);
|
|
6
|
+
}
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, {
|
|
10
|
+
get: all[name],
|
|
11
|
+
enumerable: true,
|
|
12
|
+
configurable: true,
|
|
13
|
+
set: __exportSetter.bind(all, name)
|
|
14
|
+
});
|
|
15
|
+
};
|
|
16
|
+
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
17
|
+
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
18
|
+
|
|
19
|
+
// src/cloud/x402-payment-handler.ts
|
|
20
|
+
import { logger } from "@elizaos/core";
|
|
21
|
+
function readString(value) {
|
|
22
|
+
if (typeof value !== "string")
|
|
23
|
+
return null;
|
|
24
|
+
const trimmed = value.trim();
|
|
25
|
+
return trimmed.length > 0 ? trimmed : null;
|
|
26
|
+
}
|
|
27
|
+
function readAmount(value) {
|
|
28
|
+
if (typeof value === "string") {
|
|
29
|
+
const trimmed = value.trim();
|
|
30
|
+
return trimmed.length > 0 ? trimmed : null;
|
|
31
|
+
}
|
|
32
|
+
if (typeof value === "number" && Number.isFinite(value)) {
|
|
33
|
+
return String(value);
|
|
34
|
+
}
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
function normalizeRequirement(raw) {
|
|
38
|
+
if (!raw || typeof raw !== "object")
|
|
39
|
+
return null;
|
|
40
|
+
const amount = readAmount(raw.amount);
|
|
41
|
+
const asset = readString(raw.asset);
|
|
42
|
+
const network = readString(raw.network);
|
|
43
|
+
const payTo = readString(raw.payTo);
|
|
44
|
+
if (!amount || !asset || !network || !payTo)
|
|
45
|
+
return null;
|
|
46
|
+
const scheme = readString(raw.scheme) ?? "exact";
|
|
47
|
+
return {
|
|
48
|
+
amount,
|
|
49
|
+
asset,
|
|
50
|
+
network,
|
|
51
|
+
payTo,
|
|
52
|
+
scheme,
|
|
53
|
+
expiresAt: readString(raw.expiresAt),
|
|
54
|
+
description: readString(raw.description)
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
function parseRequirementsArray(raw) {
|
|
58
|
+
if (!Array.isArray(raw))
|
|
59
|
+
return [];
|
|
60
|
+
const out = [];
|
|
61
|
+
for (const entry of raw) {
|
|
62
|
+
const normalized = normalizeRequirement(entry);
|
|
63
|
+
if (normalized)
|
|
64
|
+
out.push(normalized);
|
|
65
|
+
}
|
|
66
|
+
return out;
|
|
67
|
+
}
|
|
68
|
+
async function parseX402Response(response) {
|
|
69
|
+
const headerValue = response.headers.get("www-authenticate");
|
|
70
|
+
if (headerValue?.toLowerCase().startsWith("x402")) {
|
|
71
|
+
const jsonPart = headerValue.slice(4).trim();
|
|
72
|
+
if (jsonPart.length > 0) {
|
|
73
|
+
const parsed = JSON.parse(jsonPart);
|
|
74
|
+
const requirements2 = Array.isArray(parsed) ? parseRequirementsArray(parsed) : parseRequirementsArray(parsed.paymentRequirements ?? parsed.accepts);
|
|
75
|
+
if (requirements2.length > 0)
|
|
76
|
+
return requirements2;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
const cloned = response.clone();
|
|
80
|
+
const text = await cloned.text();
|
|
81
|
+
if (text.length === 0)
|
|
82
|
+
return null;
|
|
83
|
+
const body = JSON.parse(text);
|
|
84
|
+
const requirements = parseRequirementsArray(body.paymentRequirements ?? body.accepts);
|
|
85
|
+
return requirements.length > 0 ? requirements : null;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
class PaymentRequiredError extends Error {
|
|
89
|
+
code = "PAYMENT_REQUIRED";
|
|
90
|
+
requirements;
|
|
91
|
+
constructor(requirements, message) {
|
|
92
|
+
const text = message ?? `Eliza Cloud returned HTTP 402 — your credit balance can't cover this call. ${requirements.length} payment option(s) available.`;
|
|
93
|
+
super(text);
|
|
94
|
+
this.name = "PaymentRequiredError";
|
|
95
|
+
this.requirements = requirements;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
async function requestPayment(runtime, requirements) {
|
|
99
|
+
if (requirements.length === 0) {
|
|
100
|
+
throw new Error("[x402] requestPayment called with no requirements — adapter bug");
|
|
101
|
+
}
|
|
102
|
+
const preferred = requirements[0];
|
|
103
|
+
logger.warn({
|
|
104
|
+
boundary: "elizacloud",
|
|
105
|
+
integration: "x402",
|
|
106
|
+
asset: preferred.asset,
|
|
107
|
+
network: preferred.network,
|
|
108
|
+
amount: preferred.amount,
|
|
109
|
+
runtimeId: runtime.agentId
|
|
110
|
+
}, `[x402] payment-required: ${preferred.amount} ${preferred.asset} on ${preferred.network} → ${preferred.payTo}${preferred.description ? ` (${preferred.description})` : ""}`);
|
|
111
|
+
return { status: "surfaced", requirement: preferred, txId: null };
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// src/cloud/duffel-client.ts
|
|
115
|
+
import { logger as logger2 } from "@elizaos/core";
|
|
116
|
+
class DuffelConfigError extends Error {
|
|
117
|
+
code = "DUFFEL_NOT_CONFIGURED";
|
|
118
|
+
constructor(message) {
|
|
119
|
+
super(message);
|
|
120
|
+
this.name = "DuffelConfigError";
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
var DUFFEL_API_BASE_DEFAULT = "https://api.duffel.com";
|
|
124
|
+
var DUFFEL_API_VERSION = "v2";
|
|
125
|
+
var DEFAULT_CLOUD_RELAY_BASE = "http://127.0.0.1:31337";
|
|
126
|
+
var NOOP_DUFFEL_SPAN = {
|
|
127
|
+
success() {},
|
|
128
|
+
failure() {}
|
|
129
|
+
};
|
|
130
|
+
function getDuffelApiBase() {
|
|
131
|
+
return process.env.LIFEOPS_DUFFEL_API_BASE?.trim() || DUFFEL_API_BASE_DEFAULT;
|
|
132
|
+
}
|
|
133
|
+
function resolveDirectFlag(env) {
|
|
134
|
+
const value = env.ELIZA_DUFFEL_DIRECT?.trim().toLowerCase();
|
|
135
|
+
return value === "1" || value === "true";
|
|
136
|
+
}
|
|
137
|
+
function resolveLocalApiBase(env) {
|
|
138
|
+
const port = env.ELIZA_API_PORT?.trim();
|
|
139
|
+
if (port && /^\d+$/.test(port)) {
|
|
140
|
+
return `http://127.0.0.1:${port}`;
|
|
141
|
+
}
|
|
142
|
+
return DEFAULT_CLOUD_RELAY_BASE;
|
|
143
|
+
}
|
|
144
|
+
function readDuffelConfigFromEnv(env = process.env) {
|
|
145
|
+
if (resolveDirectFlag(env)) {
|
|
146
|
+
const apiKey = env.DUFFEL_API_KEY?.trim();
|
|
147
|
+
if (!apiKey) {
|
|
148
|
+
throw new DuffelConfigError("Duffel direct mode requested but DUFFEL_API_KEY is not set.");
|
|
149
|
+
}
|
|
150
|
+
return { mode: "direct", apiKey, cloudRelayBaseUrl: null };
|
|
151
|
+
}
|
|
152
|
+
return {
|
|
153
|
+
mode: "cloud",
|
|
154
|
+
apiKey: null,
|
|
155
|
+
cloudRelayBaseUrl: resolveLocalApiBase(env)
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
var DIRECT_MODE_COST = {
|
|
159
|
+
totalUsd: 0,
|
|
160
|
+
creatorMarkupUsd: 0,
|
|
161
|
+
platformFeeUsd: 0,
|
|
162
|
+
markupPercent: null,
|
|
163
|
+
metered: false
|
|
164
|
+
};
|
|
165
|
+
function buildHeaders(apiKey) {
|
|
166
|
+
return {
|
|
167
|
+
Authorization: `Bearer ${apiKey}`,
|
|
168
|
+
"Content-Type": "application/json",
|
|
169
|
+
"Duffel-Version": DUFFEL_API_VERSION,
|
|
170
|
+
Accept: "application/json"
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
function mapOffer(raw) {
|
|
174
|
+
const cabinClass = raw.slices[0]?.fare_brand_name ?? null;
|
|
175
|
+
const slices = raw.slices.map((slice) => ({
|
|
176
|
+
origin: slice.origin.iata_code,
|
|
177
|
+
destination: slice.destination.iata_code,
|
|
178
|
+
duration: slice.duration,
|
|
179
|
+
segments: slice.segments.map((seg) => ({
|
|
180
|
+
origin: seg.origin.iata_code,
|
|
181
|
+
destination: seg.destination.iata_code,
|
|
182
|
+
departingAt: seg.departing_at,
|
|
183
|
+
arrivingAt: seg.arriving_at,
|
|
184
|
+
carrierIataCode: seg.operating_carrier.iata_code,
|
|
185
|
+
flightNumber: seg.flight_number ?? "",
|
|
186
|
+
duration: seg.duration
|
|
187
|
+
}))
|
|
188
|
+
}));
|
|
189
|
+
const passengers = raw.passengers.map((passenger, index) => ({
|
|
190
|
+
id: passenger.id?.trim() || `passenger_${index}`,
|
|
191
|
+
type: passenger.type?.trim() || "adult",
|
|
192
|
+
givenName: passenger.given_name?.trim() || null,
|
|
193
|
+
familyName: passenger.family_name?.trim() || null
|
|
194
|
+
}));
|
|
195
|
+
const paymentRequirements = raw.payment_requirements ? {
|
|
196
|
+
requiresInstantPayment: raw.payment_requirements.requires_instant_payment !== false,
|
|
197
|
+
priceGuaranteeExpiresAt: raw.payment_requirements.price_guarantee_expires_at ?? null,
|
|
198
|
+
paymentRequiredBy: raw.payment_requirements.payment_required_by ?? null
|
|
199
|
+
} : null;
|
|
200
|
+
return {
|
|
201
|
+
id: raw.id,
|
|
202
|
+
totalAmount: raw.total_amount,
|
|
203
|
+
totalCurrency: raw.total_currency,
|
|
204
|
+
passengerCount: passengers.length > 0 ? passengers.length : 1,
|
|
205
|
+
slices,
|
|
206
|
+
expiresAt: raw.expires_at,
|
|
207
|
+
cabinClass,
|
|
208
|
+
passengers,
|
|
209
|
+
paymentRequirements
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
function mapOrder(raw) {
|
|
213
|
+
return {
|
|
214
|
+
id: raw.id,
|
|
215
|
+
bookingReference: raw.booking_reference ?? null,
|
|
216
|
+
totalAmount: raw.total_amount,
|
|
217
|
+
totalCurrency: raw.total_currency,
|
|
218
|
+
slices: raw.slices.map((slice) => ({
|
|
219
|
+
origin: slice.origin.iata_code,
|
|
220
|
+
destination: slice.destination.iata_code,
|
|
221
|
+
duration: slice.duration,
|
|
222
|
+
segments: slice.segments.map((segment) => ({
|
|
223
|
+
origin: segment.origin.iata_code,
|
|
224
|
+
destination: segment.destination.iata_code,
|
|
225
|
+
departingAt: segment.departing_at,
|
|
226
|
+
arrivingAt: segment.arriving_at,
|
|
227
|
+
carrierIataCode: segment.operating_carrier.iata_code,
|
|
228
|
+
flightNumber: segment.flight_number ?? "",
|
|
229
|
+
duration: segment.duration
|
|
230
|
+
}))
|
|
231
|
+
})),
|
|
232
|
+
passengers: raw.passengers.map((passenger, index) => ({
|
|
233
|
+
id: passenger.id?.trim() || `passenger_${index}`,
|
|
234
|
+
givenName: passenger.given_name?.trim() || null,
|
|
235
|
+
familyName: passenger.family_name?.trim() || null
|
|
236
|
+
})),
|
|
237
|
+
paymentStatus: raw.payment_status ? {
|
|
238
|
+
awaitingPayment: raw.payment_status.awaiting_payment === true,
|
|
239
|
+
paymentRequiredBy: raw.payment_status.payment_required_by ?? null,
|
|
240
|
+
priceGuaranteeExpiresAt: raw.payment_status.price_guarantee_expires_at ?? null
|
|
241
|
+
} : null,
|
|
242
|
+
documents: (raw.documents ?? []).map((document) => ({
|
|
243
|
+
type: document.type ?? null,
|
|
244
|
+
uniqueIdentifier: document.unique_identifier ?? null
|
|
245
|
+
}))
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
function mapPayment(raw) {
|
|
249
|
+
return {
|
|
250
|
+
id: raw.id,
|
|
251
|
+
orderId: raw.order_id,
|
|
252
|
+
status: raw.status,
|
|
253
|
+
currency: raw.currency,
|
|
254
|
+
amount: raw.amount,
|
|
255
|
+
type: raw.type,
|
|
256
|
+
failureReason: raw.failure_reason ?? null,
|
|
257
|
+
createdAt: raw.created_at ?? null
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
function readRelayCost(envelope) {
|
|
261
|
+
if (envelope === null || typeof envelope !== "object" || !("_meta" in envelope)) {
|
|
262
|
+
throw new Error("Duffel cloud relay response missing _meta envelope. Update Eliza Cloud or set ELIZA_DUFFEL_DIRECT=1.");
|
|
263
|
+
}
|
|
264
|
+
const meta = envelope._meta;
|
|
265
|
+
const cost = meta?.cost;
|
|
266
|
+
if (!cost || typeof cost.total_usd !== "number" || typeof cost.creator_markup_usd !== "number" || typeof cost.platform_fee_usd !== "number") {
|
|
267
|
+
throw new Error("Duffel cloud relay returned malformed _meta.cost. Refusing to proceed without billing receipt.");
|
|
268
|
+
}
|
|
269
|
+
const totalUsd = cost.total_usd;
|
|
270
|
+
const platformFeeUsd = cost.platform_fee_usd;
|
|
271
|
+
const markupPercent = totalUsd > 0 ? platformFeeUsd / totalUsd : null;
|
|
272
|
+
return {
|
|
273
|
+
totalUsd,
|
|
274
|
+
creatorMarkupUsd: cost.creator_markup_usd,
|
|
275
|
+
platformFeeUsd,
|
|
276
|
+
markupPercent,
|
|
277
|
+
metered: true
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
async function duffelFetch(args) {
|
|
281
|
+
const { config, method, directPath, cloudRelayPath, body, operation } = args;
|
|
282
|
+
const isCloud = config.mode === "cloud";
|
|
283
|
+
const url = isCloud ? `${config.cloudRelayBaseUrl ?? ""}${cloudRelayPath}` : `${getDuffelApiBase()}${directPath}`;
|
|
284
|
+
const headers = isCloud ? { "Content-Type": "application/json", Accept: "application/json" } : buildHeaders(config.apiKey ?? "");
|
|
285
|
+
const span = NOOP_DUFFEL_SPAN;
|
|
286
|
+
let response;
|
|
287
|
+
try {
|
|
288
|
+
response = await fetch(url, {
|
|
289
|
+
method,
|
|
290
|
+
headers,
|
|
291
|
+
body: body !== undefined ? JSON.stringify(body) : undefined,
|
|
292
|
+
signal: AbortSignal.timeout(30000)
|
|
293
|
+
});
|
|
294
|
+
} catch (error) {
|
|
295
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
296
|
+
logger2.error({
|
|
297
|
+
boundary: "elizacloud",
|
|
298
|
+
integration: "duffel",
|
|
299
|
+
operation,
|
|
300
|
+
mode: config.mode,
|
|
301
|
+
err: error instanceof Error ? error : undefined
|
|
302
|
+
}, `[elizacloud-duffel] Duffel ${operation} network error: ${msg}`);
|
|
303
|
+
span.failure({ error, errorKind: "network_error" });
|
|
304
|
+
throw new Error(`Duffel ${operation} failed: ${msg}`);
|
|
305
|
+
}
|
|
306
|
+
if (response.status === 402 && isCloud) {
|
|
307
|
+
const requirements = await parseX402Response(response);
|
|
308
|
+
logger2.warn({
|
|
309
|
+
boundary: "elizacloud",
|
|
310
|
+
integration: "duffel",
|
|
311
|
+
operation,
|
|
312
|
+
mode: config.mode,
|
|
313
|
+
statusCode: 402,
|
|
314
|
+
requirementCount: requirements?.length ?? 0
|
|
315
|
+
}, `[elizacloud-duffel] Duffel ${operation} returned 402 payment-required`);
|
|
316
|
+
span.failure({ statusCode: 402, errorKind: "payment_required" });
|
|
317
|
+
if (!requirements || requirements.length === 0) {
|
|
318
|
+
throw new PaymentRequiredError([], `Duffel ${operation} requires payment but the upstream did not advertise any payment options.`);
|
|
319
|
+
}
|
|
320
|
+
throw new PaymentRequiredError(requirements);
|
|
321
|
+
}
|
|
322
|
+
if (!response.ok) {
|
|
323
|
+
const errorBody = await response.text().catch(() => "");
|
|
324
|
+
const errorMsg = errorBody || `HTTP ${response.status}`;
|
|
325
|
+
logger2.warn({
|
|
326
|
+
boundary: "elizacloud",
|
|
327
|
+
integration: "duffel",
|
|
328
|
+
operation,
|
|
329
|
+
mode: config.mode,
|
|
330
|
+
statusCode: response.status
|
|
331
|
+
}, `[elizacloud-duffel] Duffel ${operation} HTTP error: ${errorMsg}`);
|
|
332
|
+
span.failure({ statusCode: response.status, errorKind: "http_error" });
|
|
333
|
+
throw new Error(`Duffel ${operation} failed (${response.status}): ${errorMsg}`);
|
|
334
|
+
}
|
|
335
|
+
const payload = await response.json();
|
|
336
|
+
span.success({ statusCode: response.status });
|
|
337
|
+
const cost = isCloud ? readRelayCost(payload) : DIRECT_MODE_COST;
|
|
338
|
+
return { data: payload, cost };
|
|
339
|
+
}
|
|
340
|
+
async function searchFlights(request, config) {
|
|
341
|
+
const resolvedConfig = config ?? readDuffelConfigFromEnv();
|
|
342
|
+
const passengerCount = Math.max(1, Math.round(request.passengers ?? 1));
|
|
343
|
+
const slices = [
|
|
344
|
+
{
|
|
345
|
+
origin: request.origin.toUpperCase().trim(),
|
|
346
|
+
destination: request.destination.toUpperCase().trim(),
|
|
347
|
+
departure_date: request.departureDate
|
|
348
|
+
}
|
|
349
|
+
];
|
|
350
|
+
if (request.returnDate) {
|
|
351
|
+
slices.push({
|
|
352
|
+
origin: request.destination.toUpperCase().trim(),
|
|
353
|
+
destination: request.origin.toUpperCase().trim(),
|
|
354
|
+
departure_date: request.returnDate
|
|
355
|
+
});
|
|
356
|
+
}
|
|
357
|
+
const requestBody = {
|
|
358
|
+
data: {
|
|
359
|
+
slices,
|
|
360
|
+
passengers: Array.from({ length: passengerCount }, () => ({
|
|
361
|
+
type: "adult"
|
|
362
|
+
})),
|
|
363
|
+
cabin_class: "economy"
|
|
364
|
+
}
|
|
365
|
+
};
|
|
366
|
+
logger2.info({
|
|
367
|
+
boundary: "elizacloud",
|
|
368
|
+
integration: "duffel",
|
|
369
|
+
origin: request.origin,
|
|
370
|
+
destination: request.destination
|
|
371
|
+
}, `[elizacloud-duffel] Searching flights ${request.origin} → ${request.destination} on ${request.departureDate}`);
|
|
372
|
+
const { data: responseData, cost } = await duffelFetch({
|
|
373
|
+
config: resolvedConfig,
|
|
374
|
+
method: "POST",
|
|
375
|
+
directPath: "/air/offer_requests?return_offers=true",
|
|
376
|
+
cloudRelayPath: "/api/cloud/travel-providers/duffel/offer-requests",
|
|
377
|
+
body: requestBody,
|
|
378
|
+
operation: "offer_request"
|
|
379
|
+
});
|
|
380
|
+
const offers = responseData.data.offers.map(mapOffer);
|
|
381
|
+
logger2.info({
|
|
382
|
+
boundary: "elizacloud",
|
|
383
|
+
integration: "duffel",
|
|
384
|
+
offerRequestId: responseData.data.id,
|
|
385
|
+
offerCount: offers.length,
|
|
386
|
+
costUsd: cost.totalUsd
|
|
387
|
+
}, `[elizacloud-duffel] Duffel returned ${offers.length} offers for request ${responseData.data.id}`);
|
|
388
|
+
return {
|
|
389
|
+
offerRequestId: responseData.data.id,
|
|
390
|
+
offers,
|
|
391
|
+
cost
|
|
392
|
+
};
|
|
393
|
+
}
|
|
394
|
+
async function getOffer(id, config) {
|
|
395
|
+
const resolvedConfig = config ?? readDuffelConfigFromEnv();
|
|
396
|
+
if (!id || id.trim().length === 0) {
|
|
397
|
+
throw new Error("Duffel getOffer: offer id is required");
|
|
398
|
+
}
|
|
399
|
+
const { data: responseData } = await duffelFetch({
|
|
400
|
+
config: resolvedConfig,
|
|
401
|
+
method: "GET",
|
|
402
|
+
directPath: `/air/offers/${encodeURIComponent(id.trim())}`,
|
|
403
|
+
cloudRelayPath: `/api/cloud/travel-providers/duffel/offers/${encodeURIComponent(id.trim())}`,
|
|
404
|
+
operation: "offer_retrieve"
|
|
405
|
+
});
|
|
406
|
+
return mapOffer(responseData.data);
|
|
407
|
+
}
|
|
408
|
+
async function createOrder(request, config) {
|
|
409
|
+
const resolvedConfig = config ?? readDuffelConfigFromEnv();
|
|
410
|
+
if (request.selectedOffers.length !== 1) {
|
|
411
|
+
throw new Error("Duffel createOrder: exactly one selected offer is required");
|
|
412
|
+
}
|
|
413
|
+
if (request.passengers.length === 0) {
|
|
414
|
+
throw new Error("Duffel createOrder: at least one passenger is required");
|
|
415
|
+
}
|
|
416
|
+
const data = {
|
|
417
|
+
type: request.type,
|
|
418
|
+
selected_offers: [...request.selectedOffers],
|
|
419
|
+
passengers: request.passengers.map((passenger) => ({
|
|
420
|
+
id: passenger.id,
|
|
421
|
+
title: passenger.title,
|
|
422
|
+
gender: passenger.gender,
|
|
423
|
+
given_name: passenger.givenName,
|
|
424
|
+
family_name: passenger.familyName,
|
|
425
|
+
born_on: passenger.bornOn,
|
|
426
|
+
email: passenger.email,
|
|
427
|
+
phone_number: passenger.phoneNumber
|
|
428
|
+
}))
|
|
429
|
+
};
|
|
430
|
+
if (request.payment) {
|
|
431
|
+
data.payments = [
|
|
432
|
+
{
|
|
433
|
+
type: request.payment.type,
|
|
434
|
+
amount: request.payment.amount,
|
|
435
|
+
currency: request.payment.currency
|
|
436
|
+
}
|
|
437
|
+
];
|
|
438
|
+
}
|
|
439
|
+
if (request.metadata && Object.keys(request.metadata).length > 0) {
|
|
440
|
+
data.metadata = request.metadata;
|
|
441
|
+
}
|
|
442
|
+
const { data: response } = await duffelFetch({
|
|
443
|
+
config: resolvedConfig,
|
|
444
|
+
method: "POST",
|
|
445
|
+
directPath: "/air/orders",
|
|
446
|
+
cloudRelayPath: "/api/cloud/travel-providers/duffel/orders",
|
|
447
|
+
body: { data },
|
|
448
|
+
operation: "order_create"
|
|
449
|
+
});
|
|
450
|
+
return mapOrder(response.data);
|
|
451
|
+
}
|
|
452
|
+
async function getOrder(orderId, config) {
|
|
453
|
+
const resolvedConfig = config ?? readDuffelConfigFromEnv();
|
|
454
|
+
if (!orderId || orderId.trim().length === 0) {
|
|
455
|
+
throw new Error("Duffel getOrder: order id is required");
|
|
456
|
+
}
|
|
457
|
+
const { data: response } = await duffelFetch({
|
|
458
|
+
config: resolvedConfig,
|
|
459
|
+
method: "GET",
|
|
460
|
+
directPath: `/air/orders/${encodeURIComponent(orderId.trim())}`,
|
|
461
|
+
cloudRelayPath: `/api/cloud/travel-providers/duffel/orders/${encodeURIComponent(orderId.trim())}`,
|
|
462
|
+
operation: "order_retrieve"
|
|
463
|
+
});
|
|
464
|
+
return mapOrder(response.data);
|
|
465
|
+
}
|
|
466
|
+
async function createPayment(args, config) {
|
|
467
|
+
const resolvedConfig = config ?? readDuffelConfigFromEnv();
|
|
468
|
+
if (args.orderId.trim().length === 0) {
|
|
469
|
+
throw new Error("Duffel createPayment: order id is required");
|
|
470
|
+
}
|
|
471
|
+
if (args.amount.trim().length === 0) {
|
|
472
|
+
throw new Error("Duffel createPayment: amount is required");
|
|
473
|
+
}
|
|
474
|
+
if (args.currency.trim().length === 0) {
|
|
475
|
+
throw new Error("Duffel createPayment: currency is required");
|
|
476
|
+
}
|
|
477
|
+
const { data: response } = await duffelFetch({
|
|
478
|
+
config: resolvedConfig,
|
|
479
|
+
method: "POST",
|
|
480
|
+
directPath: "/air/payments",
|
|
481
|
+
cloudRelayPath: "/api/cloud/travel-providers/duffel/payments",
|
|
482
|
+
body: {
|
|
483
|
+
data: {
|
|
484
|
+
order_id: args.orderId.trim(),
|
|
485
|
+
payment: {
|
|
486
|
+
type: "balance",
|
|
487
|
+
amount: args.amount.trim(),
|
|
488
|
+
currency: args.currency.trim().toUpperCase()
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
},
|
|
492
|
+
operation: "payment_create"
|
|
493
|
+
});
|
|
494
|
+
return mapPayment(response.data);
|
|
495
|
+
}
|
|
496
|
+
export {
|
|
497
|
+
searchFlights,
|
|
498
|
+
readDuffelConfigFromEnv,
|
|
499
|
+
getOrder,
|
|
500
|
+
getOffer,
|
|
501
|
+
createPayment,
|
|
502
|
+
createOrder,
|
|
503
|
+
DuffelConfigError
|
|
504
|
+
};
|
|
505
|
+
|
|
506
|
+
//# debugId=ED2CEB38A73C762A64756E2164756E21
|