@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.
Files changed (285) hide show
  1. package/README.md +20 -44
  2. package/auto-enable.ts +10 -5
  3. package/dist/browser/index.browser.js +2 -2
  4. package/dist/browser/index.browser.js.map +4 -4
  5. package/dist/cjs/index.node.cjs +2874 -5915
  6. package/dist/cjs/index.node.js.map +47 -116
  7. package/dist/cloud/auth-service-types.d.ts +8 -0
  8. package/dist/cloud/auth-service-types.d.ts.map +1 -0
  9. package/dist/cloud/auth-service-types.js +36 -0
  10. package/dist/cloud/auth-service-types.js.map +10 -0
  11. package/dist/cloud/auth.js +4 -51
  12. package/dist/cloud/auth.js.map +4 -4
  13. package/dist/cloud/base-url.d.ts +6 -2
  14. package/dist/cloud/base-url.d.ts.map +1 -1
  15. package/dist/cloud/base-url.js +3 -51
  16. package/dist/cloud/base-url.js.map +3 -3
  17. package/dist/cloud/bridge-client.d.ts +3 -3
  18. package/dist/cloud/bridge-client.d.ts.map +1 -1
  19. package/dist/cloud/bridge-client.js +3 -51
  20. package/dist/cloud/bridge-client.js.map +3 -3
  21. package/dist/cloud/clack-observer.d.ts +35 -0
  22. package/dist/cloud/clack-observer.d.ts.map +1 -0
  23. package/dist/cloud/clack-observer.js +143 -0
  24. package/dist/cloud/clack-observer.js.map +10 -0
  25. package/dist/cloud/cloud-manager.js +45 -92
  26. package/dist/cloud/cloud-manager.js.map +6 -6
  27. package/dist/cloud/cloud-wallet.js +2 -4835
  28. package/dist/cloud/cloud-wallet.js.map +3 -82
  29. package/dist/cloud/duffel-client.d.ts +181 -0
  30. package/dist/cloud/duffel-client.d.ts.map +1 -0
  31. package/dist/cloud/duffel-client.js +506 -0
  32. package/dist/cloud/duffel-client.js.map +11 -0
  33. package/dist/cloud/index.d.ts +6 -0
  34. package/dist/cloud/index.d.ts.map +1 -1
  35. package/dist/cloud/index.js +1782 -1
  36. package/dist/cloud/index.js.map +18 -3
  37. package/dist/cloud/lifeops-schedule-sync-client.d.ts +43 -0
  38. package/dist/cloud/lifeops-schedule-sync-client.d.ts.map +1 -0
  39. package/dist/cloud/lifeops-schedule-sync-client.js +180 -0
  40. package/dist/cloud/lifeops-schedule-sync-client.js.map +11 -0
  41. package/dist/cloud/lifeops-schedule-sync-contracts.d.ts +89 -0
  42. package/dist/cloud/lifeops-schedule-sync-contracts.d.ts.map +1 -0
  43. package/dist/cloud/lifeops-schedule-sync-contracts.js +39 -0
  44. package/dist/cloud/lifeops-schedule-sync-contracts.js.map +10 -0
  45. package/dist/cloud/managed-payment-clients.d.ts +166 -0
  46. package/dist/cloud/managed-payment-clients.d.ts.map +1 -0
  47. package/dist/cloud/managed-payment-clients.js +238 -0
  48. package/dist/cloud/managed-payment-clients.js.map +11 -0
  49. package/dist/cloud/null-observer.d.ts +35 -0
  50. package/dist/cloud/null-observer.d.ts.map +1 -0
  51. package/dist/cloud/null-observer.js +45 -0
  52. package/dist/cloud/null-observer.js.map +10 -0
  53. package/dist/cloud/setup-observer.d.ts +98 -0
  54. package/dist/cloud/setup-observer.d.ts.map +1 -0
  55. package/dist/cloud/setup-observer.js +2 -0
  56. package/dist/cloud/setup-observer.js.map +9 -0
  57. package/dist/cloud/validate-url.d.ts.map +1 -1
  58. package/dist/cloud/validate-url.js +2 -1
  59. package/dist/cloud/validate-url.js.map +3 -3
  60. package/dist/cloud/x402-payment-handler.d.ts +85 -0
  61. package/dist/cloud/x402-payment-handler.d.ts.map +1 -0
  62. package/dist/cloud/x402-payment-handler.js +119 -0
  63. package/dist/cloud/x402-payment-handler.js.map +10 -0
  64. package/dist/cloud-setup.d.ts +36 -0
  65. package/dist/cloud-setup.d.ts.map +1 -0
  66. package/dist/{onboarding.js → cloud-setup.js} +139 -139
  67. package/dist/cloud-setup.js.map +14 -0
  68. package/dist/cloud-voice-catalog.d.ts +65 -0
  69. package/dist/cloud-voice-catalog.d.ts.map +1 -0
  70. package/dist/cloud-voice-catalog.js +278 -0
  71. package/dist/cloud-voice-catalog.js.map +12 -0
  72. package/dist/index.browser.d.ts +11 -0
  73. package/dist/index.browser.d.ts.map +1 -1
  74. package/dist/index.d.ts +7 -1
  75. package/dist/index.d.ts.map +1 -1
  76. package/dist/index.js +5416 -8405
  77. package/dist/index.js.map +48 -116
  78. package/dist/index.node.d.ts +8 -1
  79. package/dist/index.node.d.ts.map +1 -1
  80. package/dist/init.js +17 -4
  81. package/dist/init.js.map +4 -4
  82. package/dist/lib/cloud-connection.d.ts +0 -1
  83. package/dist/lib/cloud-connection.d.ts.map +1 -1
  84. package/dist/lib/cloud-connection.js +14 -91
  85. package/dist/lib/cloud-connection.js.map +7 -7
  86. package/dist/lib/cloud-secrets.d.ts +5 -18
  87. package/dist/lib/cloud-secrets.d.ts.map +1 -1
  88. package/dist/lib/cloud-secrets.js +8 -36
  89. package/dist/lib/cloud-secrets.js.map +3 -3
  90. package/dist/lib/config-like.d.ts +1 -1
  91. package/dist/lib/config-like.d.ts.map +1 -1
  92. package/dist/lib/config-like.js +3 -3
  93. package/dist/lib/config-like.js.map +3 -3
  94. package/dist/lib/credential-type-map.d.ts +1 -1
  95. package/dist/lib/credential-type-map.js.map +1 -1
  96. package/dist/lib/http.d.ts +0 -11
  97. package/dist/lib/http.d.ts.map +1 -1
  98. package/dist/lib/http.js.map +2 -2
  99. package/dist/lib/server-cloud-tts.d.ts +12 -25
  100. package/dist/lib/server-cloud-tts.d.ts.map +1 -1
  101. package/dist/lib/server-cloud-tts.js +31 -329
  102. package/dist/lib/server-cloud-tts.js.map +4 -7
  103. package/dist/lib/tts-debug.d.ts +5 -3
  104. package/dist/lib/tts-debug.d.ts.map +1 -1
  105. package/dist/lib/tts-debug.js +1 -34
  106. package/dist/lib/tts-debug.js.map +3 -4
  107. package/dist/models/embeddings.d.ts.map +1 -1
  108. package/dist/models/embeddings.js +79 -69
  109. package/dist/models/embeddings.js.map +6 -6
  110. package/dist/models/image.d.ts.map +1 -1
  111. package/dist/models/image.js +42 -15
  112. package/dist/models/image.js.map +6 -6
  113. package/dist/models/index.js +676 -166
  114. package/dist/models/index.js.map +11 -12
  115. package/dist/models/research.d.ts.map +1 -1
  116. package/dist/models/research.js +24 -7
  117. package/dist/models/research.js.map +6 -6
  118. package/dist/models/speech.d.ts +61 -3
  119. package/dist/models/speech.d.ts.map +1 -1
  120. package/dist/models/speech.js +173 -17
  121. package/dist/models/speech.js.map +5 -5
  122. package/dist/models/text.d.ts +106 -1
  123. package/dist/models/text.d.ts.map +1 -1
  124. package/dist/models/text.js +452 -82
  125. package/dist/models/text.js.map +7 -8
  126. package/dist/models/tokenization.d.ts.map +1 -1
  127. package/dist/models/tokenization.js.map +2 -2
  128. package/dist/models/transcription.d.ts.map +1 -1
  129. package/dist/models/transcription.js +20 -6
  130. package/dist/models/transcription.js.map +5 -5
  131. package/dist/node/index.node.js +2828 -5838
  132. package/dist/node/index.node.js.map +47 -116
  133. package/dist/plugin.d.ts.map +1 -1
  134. package/dist/plugin.js +376 -5050
  135. package/dist/plugin.js.map +16 -92
  136. package/dist/providers/openai.js +11 -2
  137. package/dist/providers/openai.js.map +3 -3
  138. package/dist/register-routes.js +376 -5050
  139. package/dist/register-routes.js.map +16 -92
  140. package/dist/routes/cloud-billing-routes.d.ts.map +1 -1
  141. package/dist/routes/cloud-billing-routes.js +17 -60
  142. package/dist/routes/cloud-billing-routes.js.map +8 -7
  143. package/dist/routes/cloud-coding-container-routes.d.ts +8 -0
  144. package/dist/routes/cloud-coding-container-routes.d.ts.map +1 -0
  145. package/dist/routes/cloud-coding-container-routes.js +214 -0
  146. package/dist/routes/cloud-coding-container-routes.js.map +11 -0
  147. package/dist/routes/cloud-compat-routes.d.ts.map +1 -1
  148. package/dist/routes/cloud-compat-routes.js +17 -60
  149. package/dist/routes/cloud-compat-routes.js.map +8 -7
  150. package/dist/routes/cloud-features-routes.js +2 -2
  151. package/dist/routes/cloud-features-routes.js.map +4 -4
  152. package/dist/routes/cloud-relay-routes.d.ts +2 -1
  153. package/dist/routes/cloud-relay-routes.d.ts.map +1 -1
  154. package/dist/routes/cloud-relay-routes.js +84 -2
  155. package/dist/routes/cloud-relay-routes.js.map +5 -4
  156. package/dist/routes/cloud-routes-autonomous.d.ts +3 -4
  157. package/dist/routes/cloud-routes-autonomous.d.ts.map +1 -1
  158. package/dist/routes/cloud-routes-autonomous.js +11 -4893
  159. package/dist/routes/cloud-routes-autonomous.js.map +8 -87
  160. package/dist/routes/cloud-routes.d.ts +2 -2
  161. package/dist/routes/cloud-routes.d.ts.map +1 -1
  162. package/dist/routes/cloud-routes.js +343 -5058
  163. package/dist/routes/cloud-routes.js.map +13 -90
  164. package/dist/routes/cloud-status-routes-autonomous.d.ts +1 -2
  165. package/dist/routes/cloud-status-routes-autonomous.d.ts.map +1 -1
  166. package/dist/routes/cloud-status-routes-autonomous.js +4 -51
  167. package/dist/routes/cloud-status-routes-autonomous.js.map +5 -5
  168. package/dist/routes/cloud-status-routes.js +14 -90
  169. package/dist/routes/cloud-status-routes.js.map +7 -7
  170. package/dist/routes/home-remote-runner-access-url.d.ts +16 -0
  171. package/dist/routes/home-remote-runner-access-url.d.ts.map +1 -0
  172. package/dist/routes/home-remote-runner-access-url.js +91 -0
  173. package/dist/routes/home-remote-runner-access-url.js.map +10 -0
  174. package/dist/routes/travel-provider-relay-routes.d.ts +9 -0
  175. package/dist/routes/travel-provider-relay-routes.d.ts.map +1 -0
  176. package/dist/routes/travel-provider-relay-routes.js +358 -0
  177. package/dist/routes/travel-provider-relay-routes.js.map +14 -0
  178. package/dist/services/cloud-auth.d.ts +1 -1
  179. package/dist/services/cloud-auth.d.ts.map +1 -1
  180. package/dist/services/cloud-auth.js +7 -2
  181. package/dist/services/cloud-auth.js.map +4 -4
  182. package/dist/services/cloud-backup.js.map +2 -2
  183. package/dist/services/cloud-bootstrap.d.ts.map +1 -1
  184. package/dist/services/cloud-bootstrap.js.map +2 -2
  185. package/dist/services/cloud-bridge.js.map +3 -3
  186. package/dist/services/cloud-container.d.ts +5 -1
  187. package/dist/services/cloud-container.d.ts.map +1 -1
  188. package/dist/services/cloud-container.js +52 -1
  189. package/dist/services/cloud-container.js.map +4 -4
  190. package/dist/services/cloud-credential-provider.js.map +2 -2
  191. package/dist/services/cloud-model-registry.js.map +2 -2
  192. package/dist/types/cloud.d.ts +1 -0
  193. package/dist/types/cloud.d.ts.map +1 -1
  194. package/dist/types/cloud.js.map +2 -2
  195. package/dist/types/index.d.ts +1 -1
  196. package/dist/types/index.d.ts.map +1 -1
  197. package/dist/utils/cloud-sdk/client.d.ts.map +1 -1
  198. package/dist/utils/cloud-sdk/client.js +136 -4
  199. package/dist/utils/cloud-sdk/client.js.map +5 -5
  200. package/dist/utils/cloud-sdk/http.js.map +1 -1
  201. package/dist/utils/cloud-sdk/public-routes.d.ts +186 -0
  202. package/dist/utils/cloud-sdk/public-routes.d.ts.map +1 -1
  203. package/dist/utils/cloud-sdk/public-routes.js +99 -1
  204. package/dist/utils/cloud-sdk/public-routes.js.map +3 -3
  205. package/dist/utils/cloud-sdk/types.d.ts +0 -2
  206. package/dist/utils/cloud-sdk/types.d.ts.map +1 -1
  207. package/dist/utils/cloud-sdk/types.js.map +1 -1
  208. package/dist/utils/config.d.ts +10 -1
  209. package/dist/utils/config.d.ts.map +1 -1
  210. package/dist/utils/config.js +12 -2
  211. package/dist/utils/config.js.map +3 -3
  212. package/dist/utils/events.d.ts +23 -2
  213. package/dist/utils/events.d.ts.map +1 -1
  214. package/dist/utils/events.js +5 -3
  215. package/dist/utils/events.js.map +3 -3
  216. package/dist/utils/sdk-client.d.ts.map +1 -1
  217. package/dist/utils/sdk-client.js +17 -4
  218. package/dist/utils/sdk-client.js.map +4 -4
  219. package/dist/utils/waifu-metering.d.ts +108 -0
  220. package/dist/utils/waifu-metering.d.ts.map +1 -0
  221. package/dist/utils/waifu-metering.js +166 -0
  222. package/dist/utils/waifu-metering.js.map +10 -0
  223. package/package.json +51 -22
  224. package/src/cloud/auth-service-types.ts +24 -0
  225. package/src/cloud/base-url.ts +6 -62
  226. package/src/cloud/clack-observer.ts +189 -0
  227. package/src/cloud/duffel-client.ts +847 -0
  228. package/src/cloud/index.ts +10 -0
  229. package/src/cloud/lifeops-schedule-sync-client.ts +245 -0
  230. package/src/cloud/lifeops-schedule-sync-contracts.ts +124 -0
  231. package/src/cloud/managed-payment-clients.ts +374 -0
  232. package/src/cloud/null-observer.ts +45 -0
  233. package/src/cloud/setup-observer.ts +125 -0
  234. package/src/cloud/validate-url.ts +7 -1
  235. package/src/cloud/x402-payment-handler.ts +215 -0
  236. package/src/cloud-setup.ts +531 -0
  237. package/src/cloud-voice-catalog.test.ts +254 -0
  238. package/src/cloud-voice-catalog.ts +246 -0
  239. package/src/index.browser.ts +29 -0
  240. package/src/index.node.ts +31 -1
  241. package/src/index.ts +76 -4
  242. package/src/lib/cloud-connection.ts +2 -4
  243. package/src/lib/cloud-secrets.ts +10 -54
  244. package/src/lib/config-like.ts +1 -1
  245. package/src/lib/credential-type-map.ts +2 -2
  246. package/src/lib/http.ts +0 -17
  247. package/src/lib/server-cloud-tts.ts +33 -341
  248. package/src/lib/tts-debug.ts +5 -34
  249. package/src/models/embeddings.ts +140 -76
  250. package/src/models/image.ts +29 -14
  251. package/src/models/research.ts +11 -1
  252. package/src/models/speech.ts +269 -23
  253. package/src/models/text.ts +704 -110
  254. package/src/models/tokenization.ts +2 -2
  255. package/src/models/transcription.ts +7 -3
  256. package/src/plugin.ts +38 -0
  257. package/src/routes/cloud-billing-routes.ts +4 -14
  258. package/src/routes/cloud-coding-container-routes.ts +198 -0
  259. package/src/routes/cloud-compat-routes.ts +4 -14
  260. package/src/routes/cloud-features-routes.ts +1 -1
  261. package/src/routes/cloud-relay-routes.ts +47 -1
  262. package/src/routes/cloud-routes-autonomous.ts +7 -10
  263. package/src/routes/cloud-routes.ts +68 -7
  264. package/src/routes/cloud-status-routes-autonomous.ts +6 -2
  265. package/src/routes/home-remote-runner-access-url.ts +83 -0
  266. package/src/routes/travel-provider-relay-routes.ts +193 -0
  267. package/src/services/cloud-auth.ts +9 -2
  268. package/src/services/cloud-bootstrap.ts +1 -3
  269. package/src/services/cloud-bridge.ts +1 -1
  270. package/src/services/cloud-container.ts +93 -0
  271. package/src/services/cloud-credential-provider.ts +1 -1
  272. package/src/services/cloud-model-registry.ts +1 -1
  273. package/src/types/cloud.ts +22 -0
  274. package/src/types/index.ts +19 -0
  275. package/src/utils/cloud-sdk/client.ts +42 -3
  276. package/src/utils/cloud-sdk/public-routes.ts +168 -0
  277. package/src/utils/cloud-sdk/types.ts +0 -2
  278. package/src/utils/config.ts +20 -1
  279. package/src/utils/events.ts +30 -2
  280. package/src/utils/sdk-client.ts +5 -1
  281. package/src/utils/waifu-metering.ts +302 -0
  282. package/dist/onboarding.d.ts +0 -35
  283. package/dist/onboarding.d.ts.map +0 -1
  284. package/dist/onboarding.js.map +0 -14
  285. package/src/onboarding.ts +0 -396
@@ -0,0 +1,108 @@
1
+ /**
2
+ * Waifu metering bridge.
3
+ *
4
+ * A hosted waifu agent runs as a sandboxed container whose model inference is
5
+ * routed through the Eliza Cloud metered inference gateway. The gateway is the
6
+ * honest meter: it owns the per-model pricing table and the platform markup,
7
+ * and it debits the organization's credit balance on every call. That debit is
8
+ * authoritative and already happens server-side.
9
+ *
10
+ * What was missing is the *signal back to waifu*: waifu's burn rollup
11
+ * (`apps/worker/src/processors/agent-rollup.ts`) reads `inference.spent`
12
+ * agent_events to compute `agentDailyBurnUsd` / `agentRunwayDays`, but falls
13
+ * back to a $5/day default estimate when no such events exist. Nothing emitted them.
14
+ *
15
+ * This bridge listens for the runtime `MODEL_USED` event (emitted by the cloud
16
+ * model handlers after each inference) and POSTs a signed `inference.spent`
17
+ * webhook to waifu's receiver (`POST /webhooks/eliza-cloud/inference`). It is
18
+ * inactive unless the container is provisioned with the waifu metering env knobs,
19
+ * so it never fires for non-hosted (local dev / standalone) agents.
20
+ *
21
+ * Token counts are exact (reported by the gateway). USD is the authoritative
22
+ * post-markup cost when the gateway surfaces it (`usage.cost_usd` /
23
+ * `X-Eliza-Cost-Usd`); otherwise a conservative token-based estimate is used,
24
+ * configurable per-model via WAIFU_METER_USD_PER_1K_INPUT / _OUTPUT. The credit
25
+ * debit itself is always the cloud's authoritative number; the estimate only
26
+ * affects waifu's burn display until the cloud cost is wired through.
27
+ */
28
+ import { type IAgentRuntime } from "@elizaos/core";
29
+ import type { ModelUsageEventPayload } from "./events";
30
+ /**
31
+ * The MODEL_USED event `source` set by the Eliza Cloud metered inference path
32
+ * (see ./events.ts emitModelUsageEvent). ElizaOS event dispatch is global: every
33
+ * MODEL_USED handler receives every MODEL_USED event regardless of which plugin
34
+ * emitted it. Only inference that actually went through the cloud metered
35
+ * gateway debits real credits, so we must meter only those events. Other model
36
+ * providers (e.g. plugin-local-inference emits source "local-ai" for free CPU
37
+ * inference, plugin-openrouter emits "openrouter", etc.) must never be metered
38
+ * as cloud burn.
39
+ */
40
+ export declare const CLOUD_INFERENCE_SOURCE = "elizacloud";
41
+ export interface WaifuMeteringConfig {
42
+ webhookUrl: string;
43
+ secret: string;
44
+ agentId: string;
45
+ usdPer1kInput: number;
46
+ usdPer1kOutput: number;
47
+ }
48
+ /**
49
+ * Resolve the metering config from the container environment. Returns null
50
+ * (bridge disabled) when the required knobs are absent, which is the case for
51
+ * any agent that is not a hosted waifu agent.
52
+ */
53
+ export declare function resolveWaifuMeteringConfig(runtime: IAgentRuntime): WaifuMeteringConfig | null;
54
+ /**
55
+ * Resolve the inference webhook URL from the container environment.
56
+ *
57
+ * Prefers the explicit WAIFU_INFERENCE_WEBHOOK_URL. If that is absent but a
58
+ * credits webhook URL (WAIFU_WEBHOOK_URL) is present, derive the sibling
59
+ * `/inference` receiver path from the known `/credits` path. We NEVER post
60
+ * inference events to the credits receiver: the credits mapper defaults unknown
61
+ * payloads to `credits.topped_up`, which would corrupt credit state. If we
62
+ * cannot safely derive an inference URL, return undefined so the bridge stays
63
+ * disabled.
64
+ */
65
+ export declare function resolveInferenceWebhookUrl(runtime: IAgentRuntime): string | undefined;
66
+ /**
67
+ * Map a known `/credits` webhook URL to its sibling `/inference` URL. Returns
68
+ * undefined when the input does not contain a `/credits` path segment, so we
69
+ * never accidentally post inference to a non-inference endpoint.
70
+ */
71
+ export declare function deriveInferenceUrlFromCredits(creditsUrl: string): string | undefined;
72
+ /**
73
+ * HMAC signature compatible with waifu's webhook receiver:
74
+ * `sha256=` + HMAC-SHA256 over `${timestamp}.${rawBody}`.
75
+ */
76
+ export declare function signWaifuWebhook(rawBody: string, timestamp: string, secret: string): string;
77
+ export declare function estimateUsd(config: WaifuMeteringConfig, inputTokens: number, outputTokens: number): number;
78
+ export interface InferenceSpentPayload {
79
+ agentId: string;
80
+ modelType: string;
81
+ modelName?: string;
82
+ promptTokens: number;
83
+ completionTokens: number;
84
+ totalTokens: number;
85
+ usd: number;
86
+ costSource: "gateway" | "estimate";
87
+ timestamp: string;
88
+ idempotencyKey: string;
89
+ source: "elizacloud";
90
+ }
91
+ export declare function buildInferenceSpentPayload(config: WaifuMeteringConfig, event: ModelUsageEventPayload, now?: Date): InferenceSpentPayload | null;
92
+ /**
93
+ * POST a signed `inference.spent` webhook to waifu. Best-effort: failures are
94
+ * logged but never thrown, so metering never blocks or breaks an agent reply.
95
+ * A 10s AbortSignal bounds the request so a stuck receiver can never leave a
96
+ * background fetch hanging.
97
+ */
98
+ export declare function postInferenceSpent(config: WaifuMeteringConfig, payload: InferenceSpentPayload, fetchImpl?: typeof fetch): Promise<{
99
+ ok: boolean;
100
+ status?: number;
101
+ }>;
102
+ /**
103
+ * Build the MODEL_USED event handler that forwards inference spend to waifu.
104
+ * Resolves config lazily per-event so it stays inactive until the metering env
105
+ * is present, and so config changes (rare) are picked up without a restart.
106
+ */
107
+ export declare function createWaifuMeteringHandler(fetchImpl?: typeof fetch): (payload: ModelUsageEventPayload) => Promise<void>;
108
+ //# sourceMappingURL=waifu-metering.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"waifu-metering.d.ts","sourceRoot":"","sources":["../../src/utils/waifu-metering.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAGH,OAAO,EAAE,KAAK,aAAa,EAAU,MAAM,eAAe,CAAC;AAC3D,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAC;AAKvD;;;;;;;;;GASG;AACH,eAAO,MAAM,sBAAsB,eAAe,CAAC;AAEnD,MAAM,WAAW,mBAAmB;IAClC,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;CACxB;AAuBD;;;;GAIG;AACH,wBAAgB,0BAA0B,CACxC,OAAO,EAAE,aAAa,GACrB,mBAAmB,GAAG,IAAI,CAqB5B;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,aAAa,GAAG,MAAM,GAAG,SAAS,CAerF;AAED;;;;GAIG;AACH,wBAAgB,6BAA6B,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAgBpF;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAE3F;AAED,wBAAgB,WAAW,CACzB,MAAM,EAAE,mBAAmB,EAC3B,WAAW,EAAE,MAAM,EACnB,YAAY,EAAE,MAAM,GACnB,MAAM,CAKR;AAED,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,MAAM,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,SAAS,GAAG,UAAU,CAAC;IACnC,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,YAAY,CAAC;CACtB;AAED,wBAAgB,0BAA0B,CACxC,MAAM,EAAE,mBAAmB,EAC3B,KAAK,EAAE,sBAAsB,EAC7B,GAAG,GAAE,IAAiB,GACrB,qBAAqB,GAAG,IAAI,CAkC9B;AAID;;;;;GAKG;AACH,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,mBAAmB,EAC3B,OAAO,EAAE,qBAAqB,EAC9B,SAAS,GAAE,OAAO,KAAa,GAC9B,OAAO,CAAC;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAmC3C;AAED;;;;GAIG;AACH,wBAAgB,0BAA0B,CACxC,SAAS,GAAE,OAAO,KAAa,GAC9B,CAAC,OAAO,EAAE,sBAAsB,KAAK,OAAO,CAAC,IAAI,CAAC,CAepD"}
@@ -0,0 +1,166 @@
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/utils/waifu-metering.ts
20
+ import crypto from "node:crypto";
21
+ import { logger } from "@elizaos/core";
22
+ var DEFAULT_USD_PER_1K_INPUT = 0.003;
23
+ var DEFAULT_USD_PER_1K_OUTPUT = 0.015;
24
+ var CLOUD_INFERENCE_SOURCE = "elizacloud";
25
+ function readEnv(runtime, key) {
26
+ const fromSettings = typeof runtime.getSetting === "function" ? runtime.getSetting(key) : undefined;
27
+ const value = typeof fromSettings === "string" && fromSettings || (typeof process !== "undefined" ? process.env?.[key] : undefined);
28
+ const trimmed = typeof value === "string" ? value.trim() : "";
29
+ return trimmed.length > 0 ? trimmed : undefined;
30
+ }
31
+ function readNumberEnv(runtime, key, fallback) {
32
+ const raw = readEnv(runtime, key);
33
+ if (!raw)
34
+ return fallback;
35
+ const parsed = Number(raw);
36
+ return Number.isFinite(parsed) && parsed >= 0 ? parsed : fallback;
37
+ }
38
+ function resolveWaifuMeteringConfig(runtime) {
39
+ const webhookUrl = resolveInferenceWebhookUrl(runtime);
40
+ const secret = readEnv(runtime, "WAIFU_WEBHOOK_SECRET") ?? readEnv(runtime, "WAIFU_INFERENCE_WEBHOOK_SECRET");
41
+ const agentId = readEnv(runtime, "WAIFU_AGENT_ID") ?? readEnv(runtime, "WAIFU_CORE_AGENT_ID");
42
+ if (!webhookUrl || !secret || !agentId) {
43
+ return null;
44
+ }
45
+ return {
46
+ webhookUrl,
47
+ secret,
48
+ agentId,
49
+ usdPer1kInput: readNumberEnv(runtime, "WAIFU_METER_USD_PER_1K_INPUT", DEFAULT_USD_PER_1K_INPUT),
50
+ usdPer1kOutput: readNumberEnv(runtime, "WAIFU_METER_USD_PER_1K_OUTPUT", DEFAULT_USD_PER_1K_OUTPUT)
51
+ };
52
+ }
53
+ function resolveInferenceWebhookUrl(runtime) {
54
+ const explicit = readEnv(runtime, "WAIFU_INFERENCE_WEBHOOK_URL");
55
+ if (explicit)
56
+ return explicit;
57
+ const creditsUrl = readEnv(runtime, "WAIFU_WEBHOOK_URL");
58
+ if (!creditsUrl)
59
+ return;
60
+ const derived = deriveInferenceUrlFromCredits(creditsUrl);
61
+ if (derived)
62
+ return derived;
63
+ return;
64
+ }
65
+ function deriveInferenceUrlFromCredits(creditsUrl) {
66
+ try {
67
+ const url = new URL(creditsUrl);
68
+ if (!/\/credits\/?$/.test(url.pathname)) {
69
+ return;
70
+ }
71
+ url.pathname = url.pathname.replace(/\/credits(\/?)$/, "/inference$1");
72
+ return url.toString();
73
+ } catch {
74
+ if (/\/credits\/?$/.test(creditsUrl)) {
75
+ return creditsUrl.replace(/\/credits(\/?)$/, "/inference$1");
76
+ }
77
+ return;
78
+ }
79
+ }
80
+ function signWaifuWebhook(rawBody, timestamp, secret) {
81
+ return `sha256=${crypto.createHmac("sha256", secret).update(`${timestamp}.${rawBody}`).digest("hex")}`;
82
+ }
83
+ function estimateUsd(config, inputTokens, outputTokens) {
84
+ const usd = inputTokens / 1000 * config.usdPer1kInput + outputTokens / 1000 * config.usdPer1kOutput;
85
+ return Number.isFinite(usd) && usd > 0 ? usd : 0;
86
+ }
87
+ function buildInferenceSpentPayload(config, event, now = new Date) {
88
+ const promptTokens = Math.max(0, Math.round(Number(event.tokens?.prompt ?? 0)));
89
+ const completionTokens = Math.max(0, Math.round(Number(event.tokens?.completion ?? 0)));
90
+ const totalTokens = Math.max(0, Math.round(Number(event.tokens?.total ?? promptTokens + completionTokens)));
91
+ if (totalTokens === 0 && promptTokens === 0 && completionTokens === 0) {
92
+ return null;
93
+ }
94
+ const gatewayCost = typeof event.costUsd === "number" && Number.isFinite(event.costUsd) && event.costUsd >= 0 ? event.costUsd : undefined;
95
+ const usd = gatewayCost ?? estimateUsd(config, promptTokens, completionTokens);
96
+ const timestamp = now.toISOString();
97
+ return {
98
+ agentId: config.agentId,
99
+ modelType: String(event.type ?? "unknown"),
100
+ ...event.modelName ? { modelName: event.modelName } : {},
101
+ promptTokens,
102
+ completionTokens,
103
+ totalTokens,
104
+ usd,
105
+ costSource: gatewayCost !== undefined ? "gateway" : "estimate",
106
+ timestamp,
107
+ idempotencyKey: `inference:${config.agentId}:${crypto.randomUUID()}`,
108
+ source: "elizacloud"
109
+ };
110
+ }
111
+ var POST_TIMEOUT_MS = 1e4;
112
+ async function postInferenceSpent(config, payload, fetchImpl = fetch) {
113
+ const body = JSON.stringify(payload);
114
+ const signature = signWaifuWebhook(body, payload.timestamp, config.secret);
115
+ try {
116
+ const res = await fetchImpl(config.webhookUrl, {
117
+ method: "POST",
118
+ headers: {
119
+ "content-type": "application/json",
120
+ "X-Waifu-Webhook-Signature": signature
121
+ },
122
+ body,
123
+ signal: AbortSignal.timeout(POST_TIMEOUT_MS)
124
+ });
125
+ if (!res.ok) {
126
+ logger.warn(`[waifu-metering] inference.spent POST returned ${res.status} for agent ${config.agentId}`);
127
+ return { ok: false, status: res.status };
128
+ }
129
+ logger.debug(`[waifu-metering] inference.spent posted (agent=${config.agentId} tokens=${payload.totalTokens} usd=${payload.usd.toFixed(6)} src=${payload.costSource})`);
130
+ return { ok: true, status: res.status };
131
+ } catch (err) {
132
+ const aborted = err instanceof Error && err.name === "TimeoutError";
133
+ const detail = aborted ? `timed out after ${POST_TIMEOUT_MS}ms` : err instanceof Error ? err.message : String(err);
134
+ logger.warn(`[waifu-metering] inference.spent POST failed for agent ${config.agentId}: ${detail}`);
135
+ return { ok: false };
136
+ }
137
+ }
138
+ function createWaifuMeteringHandler(fetchImpl = fetch) {
139
+ return async (payload) => {
140
+ const runtime = payload?.runtime;
141
+ if (!runtime)
142
+ return;
143
+ if (payload?.source !== CLOUD_INFERENCE_SOURCE)
144
+ return;
145
+ const config = resolveWaifuMeteringConfig(runtime);
146
+ if (!config)
147
+ return;
148
+ const spent = buildInferenceSpentPayload(config, payload);
149
+ if (!spent)
150
+ return;
151
+ await postInferenceSpent(config, spent, fetchImpl);
152
+ };
153
+ }
154
+ export {
155
+ signWaifuWebhook,
156
+ resolveWaifuMeteringConfig,
157
+ resolveInferenceWebhookUrl,
158
+ postInferenceSpent,
159
+ estimateUsd,
160
+ deriveInferenceUrlFromCredits,
161
+ createWaifuMeteringHandler,
162
+ buildInferenceSpentPayload,
163
+ CLOUD_INFERENCE_SOURCE
164
+ };
165
+
166
+ //# debugId=17310B83242297D764756E2164756E21
@@ -0,0 +1,10 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/utils/waifu-metering.ts"],
4
+ "sourcesContent": [
5
+ "/**\n * Waifu metering bridge.\n *\n * A hosted waifu agent runs as a sandboxed container whose model inference is\n * routed through the Eliza Cloud metered inference gateway. The gateway is the\n * honest meter: it owns the per-model pricing table and the platform markup,\n * and it debits the organization's credit balance on every call. That debit is\n * authoritative and already happens server-side.\n *\n * What was missing is the *signal back to waifu*: waifu's burn rollup\n * (`apps/worker/src/processors/agent-rollup.ts`) reads `inference.spent`\n * agent_events to compute `agentDailyBurnUsd` / `agentRunwayDays`, but falls\n * back to a $5/day default estimate when no such events exist. Nothing emitted them.\n *\n * This bridge listens for the runtime `MODEL_USED` event (emitted by the cloud\n * model handlers after each inference) and POSTs a signed `inference.spent`\n * webhook to waifu's receiver (`POST /webhooks/eliza-cloud/inference`). It is\n * inactive unless the container is provisioned with the waifu metering env knobs,\n * so it never fires for non-hosted (local dev / standalone) agents.\n *\n * Token counts are exact (reported by the gateway). USD is the authoritative\n * post-markup cost when the gateway surfaces it (`usage.cost_usd` /\n * `X-Eliza-Cost-Usd`); otherwise a conservative token-based estimate is used,\n * configurable per-model via WAIFU_METER_USD_PER_1K_INPUT / _OUTPUT. The credit\n * debit itself is always the cloud's authoritative number; the estimate only\n * affects waifu's burn display until the cloud cost is wired through.\n */\n\nimport crypto from \"node:crypto\";\nimport { type IAgentRuntime, logger } from \"@elizaos/core\";\nimport type { ModelUsageEventPayload } from \"./events\";\n\nconst DEFAULT_USD_PER_1K_INPUT = 0.003;\nconst DEFAULT_USD_PER_1K_OUTPUT = 0.015;\n\n/**\n * The MODEL_USED event `source` set by the Eliza Cloud metered inference path\n * (see ./events.ts emitModelUsageEvent). ElizaOS event dispatch is global: every\n * MODEL_USED handler receives every MODEL_USED event regardless of which plugin\n * emitted it. Only inference that actually went through the cloud metered\n * gateway debits real credits, so we must meter only those events. Other model\n * providers (e.g. plugin-local-inference emits source \"local-ai\" for free CPU\n * inference, plugin-openrouter emits \"openrouter\", etc.) must never be metered\n * as cloud burn.\n */\nexport const CLOUD_INFERENCE_SOURCE = \"elizacloud\";\n\nexport interface WaifuMeteringConfig {\n webhookUrl: string;\n secret: string;\n agentId: string;\n usdPer1kInput: number;\n usdPer1kOutput: number;\n}\n\nfunction readEnv(runtime: IAgentRuntime, key: string): string | undefined {\n const fromSettings =\n typeof runtime.getSetting === \"function\" ? runtime.getSetting(key) : undefined;\n const value =\n (typeof fromSettings === \"string\" && fromSettings) ||\n (typeof process !== \"undefined\" ? process.env?.[key] : undefined);\n const trimmed = typeof value === \"string\" ? value.trim() : \"\";\n return trimmed.length > 0 ? trimmed : undefined;\n}\n\nfunction readNumberEnv(\n runtime: IAgentRuntime,\n key: string,\n fallback: number\n): number {\n const raw = readEnv(runtime, key);\n if (!raw) return fallback;\n const parsed = Number(raw);\n return Number.isFinite(parsed) && parsed >= 0 ? parsed : fallback;\n}\n\n/**\n * Resolve the metering config from the container environment. Returns null\n * (bridge disabled) when the required knobs are absent, which is the case for\n * any agent that is not a hosted waifu agent.\n */\nexport function resolveWaifuMeteringConfig(\n runtime: IAgentRuntime\n): WaifuMeteringConfig | null {\n const webhookUrl = resolveInferenceWebhookUrl(runtime);\n const secret =\n readEnv(runtime, \"WAIFU_WEBHOOK_SECRET\") ?? readEnv(runtime, \"WAIFU_INFERENCE_WEBHOOK_SECRET\");\n const agentId = readEnv(runtime, \"WAIFU_AGENT_ID\") ?? readEnv(runtime, \"WAIFU_CORE_AGENT_ID\");\n\n if (!webhookUrl || !secret || !agentId) {\n return null;\n }\n\n return {\n webhookUrl,\n secret,\n agentId,\n usdPer1kInput: readNumberEnv(runtime, \"WAIFU_METER_USD_PER_1K_INPUT\", DEFAULT_USD_PER_1K_INPUT),\n usdPer1kOutput: readNumberEnv(\n runtime,\n \"WAIFU_METER_USD_PER_1K_OUTPUT\",\n DEFAULT_USD_PER_1K_OUTPUT\n ),\n };\n}\n\n/**\n * Resolve the inference webhook URL from the container environment.\n *\n * Prefers the explicit WAIFU_INFERENCE_WEBHOOK_URL. If that is absent but a\n * credits webhook URL (WAIFU_WEBHOOK_URL) is present, derive the sibling\n * `/inference` receiver path from the known `/credits` path. We NEVER post\n * inference events to the credits receiver: the credits mapper defaults unknown\n * payloads to `credits.topped_up`, which would corrupt credit state. If we\n * cannot safely derive an inference URL, return undefined so the bridge stays\n * disabled.\n */\nexport function resolveInferenceWebhookUrl(runtime: IAgentRuntime): string | undefined {\n const explicit = readEnv(runtime, \"WAIFU_INFERENCE_WEBHOOK_URL\");\n if (explicit) return explicit;\n\n const creditsUrl = readEnv(runtime, \"WAIFU_WEBHOOK_URL\");\n if (!creditsUrl) return undefined;\n\n // Only derive when the credits URL ends in a recognizable `/credits` segment.\n // Replacing the trailing `/credits` with `/inference` keeps the same host,\n // base path, and query string. Anything we cannot confidently map is treated\n // as unsafe and skipped, never reused as-is for inference.\n const derived = deriveInferenceUrlFromCredits(creditsUrl);\n if (derived) return derived;\n\n return undefined;\n}\n\n/**\n * Map a known `/credits` webhook URL to its sibling `/inference` URL. Returns\n * undefined when the input does not contain a `/credits` path segment, so we\n * never accidentally post inference to a non-inference endpoint.\n */\nexport function deriveInferenceUrlFromCredits(creditsUrl: string): string | undefined {\n try {\n const url = new URL(creditsUrl);\n if (!/\\/credits\\/?$/.test(url.pathname)) {\n return undefined;\n }\n url.pathname = url.pathname.replace(/\\/credits(\\/?)$/, \"/inference$1\");\n return url.toString();\n } catch {\n // Fall back to a string replacement for non-absolute URLs, still requiring\n // an explicit `/credits` segment so we cannot mis-route.\n if (/\\/credits\\/?$/.test(creditsUrl)) {\n return creditsUrl.replace(/\\/credits(\\/?)$/, \"/inference$1\");\n }\n return undefined;\n }\n}\n\n/**\n * HMAC signature compatible with waifu's webhook receiver:\n * `sha256=` + HMAC-SHA256 over `${timestamp}.${rawBody}`.\n */\nexport function signWaifuWebhook(rawBody: string, timestamp: string, secret: string): string {\n return `sha256=${crypto.createHmac(\"sha256\", secret).update(`${timestamp}.${rawBody}`).digest(\"hex\")}`;\n}\n\nexport function estimateUsd(\n config: WaifuMeteringConfig,\n inputTokens: number,\n outputTokens: number\n): number {\n const usd =\n (inputTokens / 1000) * config.usdPer1kInput +\n (outputTokens / 1000) * config.usdPer1kOutput;\n return Number.isFinite(usd) && usd > 0 ? usd : 0;\n}\n\nexport interface InferenceSpentPayload {\n agentId: string;\n modelType: string;\n modelName?: string;\n promptTokens: number;\n completionTokens: number;\n totalTokens: number;\n usd: number;\n costSource: \"gateway\" | \"estimate\";\n timestamp: string;\n idempotencyKey: string;\n source: \"elizacloud\";\n}\n\nexport function buildInferenceSpentPayload(\n config: WaifuMeteringConfig,\n event: ModelUsageEventPayload,\n now: Date = new Date()\n): InferenceSpentPayload | null {\n const promptTokens = Math.max(0, Math.round(Number(event.tokens?.prompt ?? 0)));\n const completionTokens = Math.max(0, Math.round(Number(event.tokens?.completion ?? 0)));\n const totalTokens = Math.max(\n 0,\n Math.round(Number(event.tokens?.total ?? promptTokens + completionTokens))\n );\n\n // Nothing was actually spent (e.g. a cached/short-circuited call with no\n // tokens). Skip so we never inflate the burn with empty events.\n if (totalTokens === 0 && promptTokens === 0 && completionTokens === 0) {\n return null;\n }\n\n const gatewayCost =\n typeof event.costUsd === \"number\" && Number.isFinite(event.costUsd) && event.costUsd >= 0\n ? event.costUsd\n : undefined;\n const usd = gatewayCost ?? estimateUsd(config, promptTokens, completionTokens);\n\n const timestamp = now.toISOString();\n return {\n agentId: config.agentId,\n modelType: String(event.type ?? \"unknown\"),\n ...(event.modelName ? { modelName: event.modelName } : {}),\n promptTokens,\n completionTokens,\n totalTokens,\n usd,\n costSource: gatewayCost !== undefined ? \"gateway\" : \"estimate\",\n timestamp,\n idempotencyKey: `inference:${config.agentId}:${crypto.randomUUID()}`,\n source: \"elizacloud\",\n };\n}\n\nconst POST_TIMEOUT_MS = 10000;\n\n/**\n * POST a signed `inference.spent` webhook to waifu. Best-effort: failures are\n * logged but never thrown, so metering never blocks or breaks an agent reply.\n * A 10s AbortSignal bounds the request so a stuck receiver can never leave a\n * background fetch hanging.\n */\nexport async function postInferenceSpent(\n config: WaifuMeteringConfig,\n payload: InferenceSpentPayload,\n fetchImpl: typeof fetch = fetch\n): Promise<{ ok: boolean; status?: number }> {\n const body = JSON.stringify(payload);\n const signature = signWaifuWebhook(body, payload.timestamp, config.secret);\n try {\n const res = await fetchImpl(config.webhookUrl, {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/json\",\n \"X-Waifu-Webhook-Signature\": signature,\n },\n body,\n signal: AbortSignal.timeout(POST_TIMEOUT_MS),\n });\n if (!res.ok) {\n logger.warn(\n `[waifu-metering] inference.spent POST returned ${res.status} for agent ${config.agentId}`\n );\n return { ok: false, status: res.status };\n }\n logger.debug(\n `[waifu-metering] inference.spent posted (agent=${config.agentId} tokens=${payload.totalTokens} usd=${payload.usd.toFixed(6)} src=${payload.costSource})`\n );\n return { ok: true, status: res.status };\n } catch (err) {\n const aborted = err instanceof Error && err.name === \"TimeoutError\";\n const detail = aborted\n ? `timed out after ${POST_TIMEOUT_MS}ms`\n : err instanceof Error\n ? err.message\n : String(err);\n logger.warn(\n `[waifu-metering] inference.spent POST failed for agent ${config.agentId}: ${detail}`\n );\n return { ok: false };\n }\n}\n\n/**\n * Build the MODEL_USED event handler that forwards inference spend to waifu.\n * Resolves config lazily per-event so it stays inactive until the metering env\n * is present, and so config changes (rare) are picked up without a restart.\n */\nexport function createWaifuMeteringHandler(\n fetchImpl: typeof fetch = fetch\n): (payload: ModelUsageEventPayload) => Promise<void> {\n return async (payload: ModelUsageEventPayload): Promise<void> => {\n const runtime = payload?.runtime;\n if (!runtime) return;\n // ElizaOS dispatches MODEL_USED globally to every registered handler, so we\n // also receive events from other model providers (local-ai, openrouter,\n // etc.). Only cloud-metered inference debits real credits; meter only that\n // source so we never bill free/local inference as cloud burn.\n if (payload?.source !== CLOUD_INFERENCE_SOURCE) return;\n const config = resolveWaifuMeteringConfig(runtime);\n if (!config) return;\n const spent = buildInferenceSpentPayload(config, payload);\n if (!spent) return;\n await postInferenceSpent(config, spent, fetchImpl);\n };\n}\n"
6
+ ],
7
+ "mappings": "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",
8
+ "debugId": "17310B83242297D764756E2164756E21",
9
+ "names": []
10
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elizaos/plugin-elizacloud",
3
- "version": "2.0.0-beta.1",
3
+ "version": "2.0.11-beta.7",
4
4
  "type": "module",
5
5
  "main": "dist/node/index.node.js",
6
6
  "module": "dist/node/index.node.js",
@@ -15,6 +15,11 @@
15
15
  "./package.json": "./package.json",
16
16
  ".": {
17
17
  "types": "./dist/node/index.d.ts",
18
+ "eliza-source": {
19
+ "types": "./src/index.node.ts",
20
+ "import": "./src/index.node.ts",
21
+ "default": "./src/index.node.ts"
22
+ },
18
23
  "browser": {
19
24
  "types": "./dist/browser/index.d.ts",
20
25
  "import": "./dist/browser/index.browser.js",
@@ -26,6 +31,17 @@
26
31
  "default": "./dist/node/index.node.js"
27
32
  },
28
33
  "default": "./dist/node/index.node.js"
34
+ },
35
+ "./*.css": "./dist/*.css",
36
+ "./*": {
37
+ "types": "./dist/*.d.ts",
38
+ "eliza-source": {
39
+ "types": "./src/*.ts",
40
+ "import": "./src/*.ts",
41
+ "default": "./src/*.ts"
42
+ },
43
+ "import": "./dist/*.js",
44
+ "default": "./dist/*.js"
29
45
  }
30
46
  },
31
47
  "files": [
@@ -48,18 +64,31 @@
48
64
  }
49
65
  },
50
66
  "dependencies": {
67
+ "@ai-sdk/gateway": "3.0.133",
51
68
  "@ai-sdk/openai": "^3.0.9",
52
- "@elizaos/cloud-sdk": "2.0.0-beta.1",
53
- "@elizaos/core": "2.0.0-beta.1",
69
+ "@ai-sdk/provider": "3.0.10",
70
+ "@ai-sdk/provider-utils": "4.0.26",
71
+ "@elizaos/cloud-sdk": "2.0.11-beta.7",
72
+ "@elizaos/core": "2.0.11-beta.7",
73
+ "@elizaos/shared": "2.0.11-beta.7",
74
+ "@noble/curves": "2.2.0",
75
+ "@noble/hashes": "1.8.0",
76
+ "@opentelemetry/api": "1.9.1",
77
+ "@scure/bip32": "1.7.0",
78
+ "@scure/bip39": "1.6.0",
79
+ "abitype": "1.2.3",
54
80
  "ai": "^6.0.30",
81
+ "isows": "1.0.7",
55
82
  "jose": "^6.2.2",
56
83
  "js-tiktoken": "^1.0.21",
57
- "undici": "8.2.0",
58
- "viem": "^2.48.8"
84
+ "ox": "0.14.20",
85
+ "undici": "8.5.0",
86
+ "viem": "^2.48.8",
87
+ "ws": "8.21.0"
59
88
  },
60
89
  "devDependencies": {
61
90
  "@biomejs/biome": "^2.4.14",
62
- "@clack/prompts": "^0.11.0",
91
+ "@clack/prompts": "^1.5.1",
63
92
  "@types/bun": "^1.3.5",
64
93
  "@types/node": "^25.0.3",
65
94
  "typescript": "^6.0.3",
@@ -70,7 +99,7 @@
70
99
  },
71
100
  "scripts": {
72
101
  "dev": "bun run build.ts --watch",
73
- "typecheck": "tsc --noEmit -p tsconfig.json",
102
+ "typecheck": "tsgo --noEmit -p tsconfig.json",
74
103
  "lint": "bunx @biomejs/biome check --write --unsafe .",
75
104
  "clean": "rm -rf dist .turbo .turbo-tsconfig.json tsconfig.tsbuildinfo",
76
105
  "format": "bunx @biomejs/biome format --write .",
@@ -105,72 +134,72 @@
105
134
  },
106
135
  "ELIZAOS_CLOUD_NANO_MODEL": {
107
136
  "type": "string",
108
- "description": "Nano/cheapest text model for lightweight routing and should-respond tasks (overrides NANO_MODEL). Default: openai/gpt-oss-120b:nitro",
137
+ "description": "Nano/cheapest text model for lightweight routing and should-respond tasks (overrides NANO_MODEL). Default: gpt-oss-120b",
109
138
  "required": false,
110
- "default": "openai/gpt-oss-120b:nitro",
139
+ "default": "gpt-oss-120b",
111
140
  "sensitive": false
112
141
  },
113
142
  "NANO_MODEL": {
114
143
  "type": "string",
115
144
  "description": "Fallback identifier for the nano language model if ELIZAOS_CLOUD_NANO_MODEL is not set.",
116
145
  "required": false,
117
- "default": "openai/gpt-oss-120b:nitro",
146
+ "default": "gpt-oss-120b",
118
147
  "sensitive": false
119
148
  },
120
149
  "ELIZAOS_CLOUD_SMALL_MODEL": {
121
150
  "type": "string",
122
- "description": "Small/fast model for quick tasks (overrides SMALL_MODEL). Default: openai/gpt-oss-120b:nitro",
151
+ "description": "Small/fast model for quick tasks (overrides SMALL_MODEL). Default: gpt-oss-120b",
123
152
  "required": false,
124
- "default": "openai/gpt-oss-120b:nitro",
153
+ "default": "gpt-oss-120b",
125
154
  "sensitive": false
126
155
  },
127
156
  "SMALL_MODEL": {
128
157
  "type": "string",
129
158
  "description": "Fallback identifier for the small language model if ELIZAOS_CLOUD_SMALL_MODEL is not set.",
130
159
  "required": false,
131
- "default": "openai/gpt-oss-120b:nitro",
160
+ "default": "gpt-oss-120b",
132
161
  "sensitive": false
133
162
  },
134
163
  "ELIZAOS_CLOUD_MEDIUM_MODEL": {
135
164
  "type": "string",
136
- "description": "Medium planning model for multi-step reasoning (overrides MEDIUM_MODEL). Default: openai/gpt-oss-120b:nitro",
165
+ "description": "Medium planning model for multi-step reasoning (overrides MEDIUM_MODEL). Default: gpt-oss-120b",
137
166
  "required": false,
138
- "default": "openai/gpt-oss-120b:nitro",
167
+ "default": "gpt-oss-120b",
139
168
  "sensitive": false
140
169
  },
141
170
  "MEDIUM_MODEL": {
142
171
  "type": "string",
143
172
  "description": "Fallback identifier for the medium language model if ELIZAOS_CLOUD_MEDIUM_MODEL is not set.",
144
173
  "required": false,
145
- "default": "openai/gpt-oss-120b:nitro",
174
+ "default": "gpt-oss-120b",
146
175
  "sensitive": false
147
176
  },
148
177
  "ELIZAOS_CLOUD_LARGE_MODEL": {
149
178
  "type": "string",
150
- "description": "Large/powerful model for complex tasks (overrides LARGE_MODEL). Default: openai/gpt-oss-120b:nitro",
179
+ "description": "Large/powerful model for complex tasks (overrides LARGE_MODEL). Default: zai-glm-4.7",
151
180
  "required": false,
152
- "default": "openai/gpt-oss-120b:nitro",
181
+ "default": "zai-glm-4.7",
153
182
  "sensitive": false
154
183
  },
155
184
  "LARGE_MODEL": {
156
185
  "type": "string",
157
186
  "description": "Fallback identifier for the large language model if ELIZAOS_CLOUD_LARGE_MODEL is not set.",
158
187
  "required": false,
159
- "default": "openai/gpt-oss-120b:nitro",
188
+ "default": "zai-glm-4.7",
160
189
  "sensitive": false
161
190
  },
162
191
  "ELIZAOS_CLOUD_MEGA_MODEL": {
163
192
  "type": "string",
164
193
  "description": "Mega/top-tier model for the heaviest generation tasks (overrides MEGA_MODEL). Falls back to the large tier when unset.",
165
194
  "required": false,
166
- "default": "openai/gpt-oss-120b:nitro",
195
+ "default": "zai-glm-4.7",
167
196
  "sensitive": false
168
197
  },
169
198
  "MEGA_MODEL": {
170
199
  "type": "string",
171
200
  "description": "Fallback identifier for the mega language model if ELIZAOS_CLOUD_MEGA_MODEL is not set.",
172
201
  "required": false,
173
- "default": "openai/gpt-oss-120b:nitro",
202
+ "default": "zai-glm-4.7",
174
203
  "sensitive": false
175
204
  },
176
205
  "ELIZAOS_CLOUD_RESPONSE_HANDLER_MODEL": {
@@ -292,7 +321,7 @@
292
321
  }
293
322
  }
294
323
  },
295
- "gitHead": "646c632924826e2b75c2304a75ee56959fe4a460",
324
+ "gitHead": "cdbc876f793d96073d7eb0d09715a031ce0cd32e",
296
325
  "eliza": {
297
326
  "platforms": [
298
327
  "browser",
@@ -0,0 +1,24 @@
1
+ import type { Service } from "@elizaos/core";
2
+
3
+ export interface CloudAuthApiKeyService {
4
+ isAuthenticated: () => boolean;
5
+ getApiKey?: () => string | undefined;
6
+ }
7
+
8
+ export function isCloudAuthApiKeyService(
9
+ value: Service | null | undefined,
10
+ ): value is Service & CloudAuthApiKeyService {
11
+ return (
12
+ value !== null &&
13
+ value !== undefined &&
14
+ typeof (value as Partial<CloudAuthApiKeyService>).isAuthenticated ===
15
+ "function"
16
+ );
17
+ }
18
+
19
+ export function normalizeCloudApiKey(value: string | null | undefined): string | null {
20
+ if (typeof value !== "string") return null;
21
+ const trimmed = value.trim();
22
+ if (!trimmed || trimmed.toUpperCase() === "[REDACTED]") return null;
23
+ return trimmed;
24
+ }
@@ -1,62 +1,6 @@
1
- const DEFAULT_CLOUD_SITE_URL = "https://www.elizacloud.ai";
2
-
3
- const LEGACY_CLOUD_HOST_ALIASES = new Set([
4
- "elizacloud.ai",
5
- "www.elizacloud.ai",
6
- ]);
7
-
8
- function isLoopbackHost(hostname: string): boolean {
9
- const normalized = hostname.toLowerCase();
10
- return (
11
- normalized === "localhost" ||
12
- normalized === "::1" ||
13
- normalized === "0:0:0:0:0:0:0:1" ||
14
- normalized.startsWith("127.")
15
- );
16
- }
17
-
18
- function trimApiPath(pathname: string): string {
19
- const normalized = pathname.trim().replace(/\/+$/, "");
20
- if (!normalized) return "";
21
- if (normalized === "/api/v1") return "";
22
- if (normalized.endsWith("/api/v1")) {
23
- return normalized.slice(0, -"/api/v1".length);
24
- }
25
- return normalized;
26
- }
27
-
28
- export function normalizeCloudSiteUrl(rawUrl?: string): string {
29
- // Allow cloud-provisioned containers to override the base URL via env var
30
- const envOverride = process.env.ELIZAOS_CLOUD_BASE_URL?.trim();
31
- const candidate = envOverride || rawUrl?.trim() || DEFAULT_CLOUD_SITE_URL;
32
-
33
- try {
34
- const parsed = new URL(candidate);
35
- const pathname = trimApiPath(parsed.pathname);
36
- const host = parsed.hostname.toLowerCase();
37
- const preserveLocalOrigin = isLoopbackHost(host);
38
-
39
- parsed.hash = "";
40
- parsed.search = "";
41
- if (!preserveLocalOrigin) {
42
- parsed.protocol = "https:";
43
- parsed.port = "";
44
- }
45
- parsed.pathname = pathname;
46
-
47
- if (LEGACY_CLOUD_HOST_ALIASES.has(host)) {
48
- parsed.hostname = "www.elizacloud.ai";
49
- parsed.pathname = "";
50
- }
51
-
52
- return parsed.toString().replace(/\/{1,1024}$/, "");
53
- } catch {
54
- const safeCandidate =
55
- candidate.length > 8192 ? candidate.slice(0, 8192) : candidate;
56
- return safeCandidate.replace(/\/{1,1024}$/, "");
57
- }
58
- }
59
-
60
- export function resolveCloudApiBaseUrl(rawUrl?: string): string {
61
- return `${normalizeCloudSiteUrl(rawUrl)}/api/v1`;
62
- }
1
+ /**
2
+ * Cloud site/API URL normalizer. The implementation moved to
3
+ * `@elizaos/shared/elizacloud/base-url` so host-layer packages can normalize
4
+ * URLs without reverse-importing this plugin.
5
+ */
6
+ export { normalizeCloudSiteUrl, resolveCloudApiBaseUrl } from "@elizaos/shared";