@teith/openclaw-runware-provider 0.3.3 → 0.3.5

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.
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Emits `openclaw.cost.usd` OpenTelemetry counter for runware completions.
3
+ *
4
+ * In openclaw 2026.6.x, session transcripts live as
5
+ * `~/.openclaw/agents/<agentId>/sessions/<sessionId>.trajectory.jsonl`
6
+ * with this per-entry shape:
7
+ *
8
+ * {
9
+ * "traceSchema": "openclaw-trajectory", "schemaVersion": 1,
10
+ * "traceId": "...", "type": "model.completed",
11
+ * "sessionKey": "agent:main:<channel>[:<frag>]",
12
+ * "provider": "runware", "modelId": "qwen35-397b-a17b-fp8",
13
+ * "data": {
14
+ * "usage": { "input", "output", "cacheRead", "total" },
15
+ * "promptCache": { "lastCallUsage": { "cacheWrite" } }
16
+ * }
17
+ * }
18
+ *
19
+ * Transcripts DO NOT carry the dollar cost — openclaw's Usage UI multiplies
20
+ * tokens by the live `model.cost` from the plugin's ProviderShape at render
21
+ * time. The diagnostic-path counter `openclaw.cost.usd` tries to do the
22
+ * same thing through `resolveModelCostConfig(...)`, which reads from a
23
+ * cache that's never seeded for runware (cache only accepts manifest
24
+ * `modelCatalog` rows + openclaw.json + OpenRouter/LiteLLM catalogs;
25
+ * runtime `catalog.run` results don't reach it). Result: counter stays at
26
+ * zero even though everything else works.
27
+ *
28
+ * This module fills that gap from inside the plugin. We:
29
+ * 1. Maintain a per-modelId pricing snapshot (input/output/cacheRead/
30
+ * cacheWrite per-million-token USD) refreshed every 30s from the
31
+ * same `fetchModels()` cache that feeds catalog.run. So pricing is
32
+ * genuinely real-time, no static manifest field, no build step.
33
+ * 2. Tail every `*.trajectory.jsonl` under `~/.openclaw/agents/<id>/sessions/`
34
+ * on a 2s interval, filtering to `type === "model.completed"`. The
35
+ * sibling `trace.artifacts` event duplicates the same usage data, so
36
+ * filtering by type prevents double-counting.
37
+ * 3. Compute USD with openclaw's own formula:
38
+ * cost = (cost_per_1M * tokens) / 1_000_000
39
+ * 4. Write to the global OTel counter `openclaw.cost.usd` with
40
+ * attributes (`openclaw.provider`, `openclaw.model`, `openclaw.channel`)
41
+ * that match what diagnostics-otel uses for `openclaw.tokens` —
42
+ * same labels → same Prometheus time series.
43
+ *
44
+ * Anchors at file size on first sighting, so only entries written after
45
+ * gateway start count (no replay of historical transcripts on every
46
+ * restart). Survives plugin hot-reload via globalThis state.
47
+ *
48
+ * Polling instead of a runtime hook because openclaw blocks `llm_output`
49
+ * and `agent_end` for non-bundled plugins unless
50
+ * `plugins.entries.<id>.hooks.allowConversationAccess: true` is set in
51
+ * openclaw.json — i.e. the manager. The trajectory file is written
52
+ * unconditionally and is plugin-readable, so no config flag needed.
53
+ */
54
+ export declare function startCostMetricPoller(opts?: {
55
+ openclawHome?: string;
56
+ intervalMs?: number;
57
+ }): void;
58
+ //# sourceMappingURL=cost-metric.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cost-metric.d.ts","sourceRoot":"","sources":["../src/cost-metric.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoDG;AA0EH,wBAAgB,qBAAqB,CAAC,IAAI,CAAC,EAAE;IAC3C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,GAAG,IAAI,CAiCP"}
@@ -0,0 +1,373 @@
1
+ /**
2
+ * Emits `openclaw.cost.usd` OpenTelemetry counter for runware completions.
3
+ *
4
+ * In openclaw 2026.6.x, session transcripts live as
5
+ * `~/.openclaw/agents/<agentId>/sessions/<sessionId>.trajectory.jsonl`
6
+ * with this per-entry shape:
7
+ *
8
+ * {
9
+ * "traceSchema": "openclaw-trajectory", "schemaVersion": 1,
10
+ * "traceId": "...", "type": "model.completed",
11
+ * "sessionKey": "agent:main:<channel>[:<frag>]",
12
+ * "provider": "runware", "modelId": "qwen35-397b-a17b-fp8",
13
+ * "data": {
14
+ * "usage": { "input", "output", "cacheRead", "total" },
15
+ * "promptCache": { "lastCallUsage": { "cacheWrite" } }
16
+ * }
17
+ * }
18
+ *
19
+ * Transcripts DO NOT carry the dollar cost — openclaw's Usage UI multiplies
20
+ * tokens by the live `model.cost` from the plugin's ProviderShape at render
21
+ * time. The diagnostic-path counter `openclaw.cost.usd` tries to do the
22
+ * same thing through `resolveModelCostConfig(...)`, which reads from a
23
+ * cache that's never seeded for runware (cache only accepts manifest
24
+ * `modelCatalog` rows + openclaw.json + OpenRouter/LiteLLM catalogs;
25
+ * runtime `catalog.run` results don't reach it). Result: counter stays at
26
+ * zero even though everything else works.
27
+ *
28
+ * This module fills that gap from inside the plugin. We:
29
+ * 1. Maintain a per-modelId pricing snapshot (input/output/cacheRead/
30
+ * cacheWrite per-million-token USD) refreshed every 30s from the
31
+ * same `fetchModels()` cache that feeds catalog.run. So pricing is
32
+ * genuinely real-time, no static manifest field, no build step.
33
+ * 2. Tail every `*.trajectory.jsonl` under `~/.openclaw/agents/<id>/sessions/`
34
+ * on a 2s interval, filtering to `type === "model.completed"`. The
35
+ * sibling `trace.artifacts` event duplicates the same usage data, so
36
+ * filtering by type prevents double-counting.
37
+ * 3. Compute USD with openclaw's own formula:
38
+ * cost = (cost_per_1M * tokens) / 1_000_000
39
+ * 4. Write to the global OTel counter `openclaw.cost.usd` with
40
+ * attributes (`openclaw.provider`, `openclaw.model`, `openclaw.channel`)
41
+ * that match what diagnostics-otel uses for `openclaw.tokens` —
42
+ * same labels → same Prometheus time series.
43
+ *
44
+ * Anchors at file size on first sighting, so only entries written after
45
+ * gateway start count (no replay of historical transcripts on every
46
+ * restart). Survives plugin hot-reload via globalThis state.
47
+ *
48
+ * Polling instead of a runtime hook because openclaw blocks `llm_output`
49
+ * and `agent_end` for non-bundled plugins unless
50
+ * `plugins.entries.<id>.hooks.allowConversationAccess: true` is set in
51
+ * openclaw.json — i.e. the manager. The trajectory file is written
52
+ * unconditionally and is plugin-readable, so no config flag needed.
53
+ */
54
+ import { createReadStream } from "node:fs";
55
+ import { readdir, stat } from "node:fs/promises";
56
+ import { homedir } from "node:os";
57
+ import { join } from "node:path";
58
+ import { fetchModels } from "./catalog.js";
59
+ import { resolveApiKey, resolveBaseUrl } from "./models.js";
60
+ const GLOBAL_KEY = "__runware_openclaw_cost_metric__";
61
+ const POLL_INTERVAL_MS = 2000;
62
+ const PRICING_REFRESH_MS = 30_000;
63
+ const RUNWARE_PROVIDER = "runware";
64
+ const METER_NAME = "runware-openclaw-provider";
65
+ const METRIC_NAME = "openclaw.cost.usd";
66
+ const TARGET_ENTRY_TYPE = "model.completed";
67
+ function loadState() {
68
+ const g = globalThis;
69
+ const existing = g[GLOBAL_KEY];
70
+ if (existing)
71
+ return existing;
72
+ const fresh = {
73
+ initialized: false,
74
+ counter: null,
75
+ counterInit: null,
76
+ emittedAny: false,
77
+ fileStates: new Map(),
78
+ intervalHandle: null,
79
+ pricingByModelId: new Map(),
80
+ lastPricingFetchAt: 0,
81
+ pricingFetchInFlight: null,
82
+ pricingLoadedLogged: false,
83
+ warnedMissingPricing: new Set(),
84
+ warnedNoApiKey: false,
85
+ warnedPricingFetchFailed: false,
86
+ };
87
+ g[GLOBAL_KEY] = fresh;
88
+ return fresh;
89
+ }
90
+ export function startCostMetricPoller(opts) {
91
+ const state = loadState();
92
+ if (state.initialized)
93
+ return;
94
+ state.initialized = true;
95
+ const openclawHome = opts?.openclawHome ??
96
+ process.env.OPENCLAW_HOME ??
97
+ join(homedir(), ".openclaw");
98
+ const intervalMs = opts?.intervalMs ?? POLL_INTERVAL_MS;
99
+ state.counterInit = initCounter()
100
+ .then((counter) => {
101
+ state.counter = counter;
102
+ })
103
+ .catch((err) => {
104
+ console.warn("[runware-cost-metric] OTel init failed:", err);
105
+ state.counter = null;
106
+ });
107
+ const tick = () => {
108
+ pollOnce(openclawHome, state).catch((err) => {
109
+ console.error("[runware-cost-metric] poll error:", err);
110
+ });
111
+ };
112
+ const handle = setInterval(tick, intervalMs);
113
+ state.intervalHandle = handle;
114
+ if (typeof handle.unref === "function")
115
+ handle.unref();
116
+ console.log(`[runware-cost-metric] started, intervalMs=${intervalMs} openclawHome=${openclawHome}`);
117
+ }
118
+ async function initCounter() {
119
+ const otel = (await import("@opentelemetry/api"));
120
+ const meter = otel.metrics.getMeter(METER_NAME);
121
+ return meter.createCounter(METRIC_NAME, {
122
+ description: "Estimated model cost in USD (emitted by runware plugin)",
123
+ unit: "USD",
124
+ });
125
+ }
126
+ async function refreshPricingIfStale(state) {
127
+ if (state.pricingFetchInFlight) {
128
+ await state.pricingFetchInFlight;
129
+ return;
130
+ }
131
+ const now = Date.now();
132
+ if (state.pricingByModelId.size > 0 &&
133
+ now - state.lastPricingFetchAt < PRICING_REFRESH_MS) {
134
+ return;
135
+ }
136
+ const apiKey = resolveApiKey({ env: process.env });
137
+ if (!apiKey) {
138
+ if (!state.warnedNoApiKey) {
139
+ state.warnedNoApiKey = true;
140
+ console.warn("[runware-cost-metric] RUNWARE_API_KEY not in env, pricing unavailable");
141
+ }
142
+ return;
143
+ }
144
+ state.warnedNoApiKey = false;
145
+ const baseUrl = resolveBaseUrl(process.env);
146
+ state.pricingFetchInFlight = (async () => {
147
+ try {
148
+ const models = await fetchModels(baseUrl, apiKey);
149
+ const next = new Map();
150
+ for (const m of models) {
151
+ next.set(m.id, {
152
+ input: m.inputCost ?? 0,
153
+ output: m.outputCost ?? 0,
154
+ cacheRead: m.cacheReadCost ?? 0,
155
+ cacheWrite: m.cacheWriteCost ?? 0,
156
+ });
157
+ }
158
+ state.pricingByModelId = next;
159
+ state.lastPricingFetchAt = Date.now();
160
+ state.warnedPricingFetchFailed = false;
161
+ if (!state.pricingLoadedLogged) {
162
+ state.pricingLoadedLogged = true;
163
+ const sample = Array.from(next.keys()).slice(0, 3).join(", ");
164
+ console.log(`[runware-cost-metric] loaded pricing for ${next.size} models (e.g. ${sample})`);
165
+ }
166
+ }
167
+ catch (err) {
168
+ if (state.pricingByModelId.size === 0 && !state.warnedPricingFetchFailed) {
169
+ state.warnedPricingFetchFailed = true;
170
+ console.warn("[runware-cost-metric] pricing fetch failed (no cached pricing):", err);
171
+ }
172
+ }
173
+ finally {
174
+ state.pricingFetchInFlight = null;
175
+ }
176
+ })();
177
+ await state.pricingFetchInFlight;
178
+ }
179
+ async function pollOnce(openclawHome, state) {
180
+ if (state.counterInit) {
181
+ await state.counterInit;
182
+ state.counterInit = null;
183
+ }
184
+ if (!state.counter)
185
+ return;
186
+ await refreshPricingIfStale(state);
187
+ if (state.pricingByModelId.size === 0)
188
+ return;
189
+ const agentsDir = join(openclawHome, "agents");
190
+ let agents;
191
+ try {
192
+ agents = await readdir(agentsDir);
193
+ }
194
+ catch {
195
+ return;
196
+ }
197
+ for (const agent of agents) {
198
+ await pollSessionsDir(join(agentsDir, agent, "sessions"), state);
199
+ }
200
+ }
201
+ async function pollSessionsDir(sessionsDir, state) {
202
+ let entries;
203
+ try {
204
+ entries = await readdir(sessionsDir);
205
+ }
206
+ catch {
207
+ return;
208
+ }
209
+ for (const entry of entries) {
210
+ if (!entry.endsWith(".trajectory.jsonl"))
211
+ continue;
212
+ await pollSessionFile(join(sessionsDir, entry), state);
213
+ }
214
+ }
215
+ async function pollSessionFile(path, state) {
216
+ let info;
217
+ try {
218
+ const s = await stat(path);
219
+ info = { ino: s.ino, size: s.size };
220
+ }
221
+ catch {
222
+ state.fileStates.delete(path);
223
+ return;
224
+ }
225
+ const prev = state.fileStates.get(path);
226
+ if (!prev) {
227
+ state.fileStates.set(path, {
228
+ offset: info.size,
229
+ inode: info.ino,
230
+ size: info.size,
231
+ });
232
+ return;
233
+ }
234
+ if (prev.inode !== info.ino || info.size < prev.size) {
235
+ state.fileStates.set(path, {
236
+ offset: info.size,
237
+ inode: info.ino,
238
+ size: info.size,
239
+ });
240
+ return;
241
+ }
242
+ if (info.size === prev.offset) {
243
+ state.fileStates.set(path, {
244
+ offset: prev.offset,
245
+ inode: info.ino,
246
+ size: info.size,
247
+ });
248
+ return;
249
+ }
250
+ const chunk = await readBytes(path, prev.offset, info.size);
251
+ const consumed = parseAndEmit(chunk, state);
252
+ state.fileStates.set(path, {
253
+ offset: prev.offset + consumed,
254
+ inode: info.ino,
255
+ size: info.size,
256
+ });
257
+ }
258
+ function readBytes(path, start, end) {
259
+ return new Promise((resolve, reject) => {
260
+ const parts = [];
261
+ const stream = createReadStream(path, {
262
+ start,
263
+ end: Math.max(start, end - 1),
264
+ encoding: "utf8",
265
+ });
266
+ stream.on("data", (chunk) => {
267
+ parts.push(typeof chunk === "string" ? chunk : chunk.toString("utf8"));
268
+ });
269
+ stream.on("end", () => resolve(parts.join("")));
270
+ stream.on("error", reject);
271
+ });
272
+ }
273
+ function parseAndEmit(chunk, state) {
274
+ if (chunk.length === 0)
275
+ return 0;
276
+ const lastNewline = chunk.lastIndexOf("\n");
277
+ if (lastNewline === -1)
278
+ return 0;
279
+ const lines = chunk.slice(0, lastNewline).split("\n");
280
+ for (const line of lines) {
281
+ if (line.length === 0 || line.trim().length === 0)
282
+ continue;
283
+ let parsed;
284
+ try {
285
+ parsed = JSON.parse(line);
286
+ }
287
+ catch {
288
+ continue;
289
+ }
290
+ emitFromEntry(parsed, state);
291
+ }
292
+ return lastNewline + 1;
293
+ }
294
+ function emitFromEntry(entry, state) {
295
+ if (!state.counter || !isRecord(entry))
296
+ return;
297
+ if (entry.type !== TARGET_ENTRY_TYPE)
298
+ return;
299
+ if (entry.provider !== RUNWARE_PROVIDER)
300
+ return;
301
+ if (typeof entry.modelId !== "string" || entry.modelId.length === 0)
302
+ return;
303
+ const modelId = entry.modelId;
304
+ const data = entry.data;
305
+ if (!isRecord(data))
306
+ return;
307
+ const usage = data.usage;
308
+ if (!isRecord(usage))
309
+ return;
310
+ const cost = state.pricingByModelId.get(modelId);
311
+ if (!cost) {
312
+ if (!state.warnedMissingPricing.has(modelId)) {
313
+ state.warnedMissingPricing.add(modelId);
314
+ console.warn(`[runware-cost-metric] no pricing for model "${modelId}" — skipping cost emit (will retry on next /v1/models refresh)`);
315
+ }
316
+ return;
317
+ }
318
+ const input = nonNegNumber(usage.input);
319
+ const output = nonNegNumber(usage.output);
320
+ const cacheRead = nonNegNumber(usage.cacheRead);
321
+ const cacheWrite = readCacheWrite(data);
322
+ const costUsd = (cost.input * input +
323
+ cost.output * output +
324
+ cost.cacheRead * cacheRead +
325
+ cost.cacheWrite * cacheWrite) /
326
+ 1_000_000;
327
+ if (!Number.isFinite(costUsd) || costUsd <= 0)
328
+ return;
329
+ const attrs = {
330
+ "openclaw.provider": RUNWARE_PROVIDER,
331
+ "openclaw.model": modelId,
332
+ };
333
+ const channel = parseChannelFromSessionKey(entry.sessionKey);
334
+ if (channel)
335
+ attrs["openclaw.channel"] = channel;
336
+ try {
337
+ state.counter.add(costUsd, attrs);
338
+ if (!state.emittedAny) {
339
+ state.emittedAny = true;
340
+ console.log(`[runware-cost-metric] first emit: ${costUsd.toFixed(6)} USD attrs=${JSON.stringify(attrs)} tokens=${JSON.stringify({ input, output, cacheRead, cacheWrite })}`);
341
+ }
342
+ }
343
+ catch (err) {
344
+ console.error("[runware-cost-metric] counter.add failed:", err);
345
+ }
346
+ }
347
+ function readCacheWrite(data) {
348
+ const pc = data.promptCache;
349
+ if (!isRecord(pc))
350
+ return 0;
351
+ const lcu = pc.lastCallUsage;
352
+ if (!isRecord(lcu))
353
+ return 0;
354
+ return nonNegNumber(lcu.cacheWrite);
355
+ }
356
+ function parseChannelFromSessionKey(sessionKey) {
357
+ if (typeof sessionKey !== "string")
358
+ return undefined;
359
+ // "agent:<agentId>:<channel>[:<sessionFragment>]"
360
+ const parts = sessionKey.split(":");
361
+ if (parts.length >= 3 && parts[0] === "agent") {
362
+ const ch = parts[2];
363
+ return typeof ch === "string" && ch.length > 0 ? ch : undefined;
364
+ }
365
+ return undefined;
366
+ }
367
+ function isRecord(v) {
368
+ return v !== null && typeof v === "object";
369
+ }
370
+ function nonNegNumber(v) {
371
+ return typeof v === "number" && Number.isFinite(v) && v >= 0 ? v : 0;
372
+ }
373
+ //# sourceMappingURL=cost-metric.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cost-metric.js","sourceRoot":"","sources":["../src/cost-metric.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoDG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAC3C,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAmC5D,MAAM,UAAU,GAAG,kCAAkC,CAAC;AACtD,MAAM,gBAAgB,GAAG,IAAI,CAAC;AAC9B,MAAM,kBAAkB,GAAG,MAAM,CAAC;AAClC,MAAM,gBAAgB,GAAG,SAAS,CAAC;AACnC,MAAM,UAAU,GAAG,2BAA2B,CAAC;AAC/C,MAAM,WAAW,GAAG,mBAAmB,CAAC;AACxC,MAAM,iBAAiB,GAAG,iBAAiB,CAAC;AAE5C,SAAS,SAAS;IAChB,MAAM,CAAC,GAAG,UAAqC,CAAC;IAChD,MAAM,QAAQ,GAAG,CAAC,CAAC,UAAU,CAA4B,CAAC;IAC1D,IAAI,QAAQ;QAAE,OAAO,QAAQ,CAAC;IAC9B,MAAM,KAAK,GAAgB;QACzB,WAAW,EAAE,KAAK;QAClB,OAAO,EAAE,IAAI;QACb,WAAW,EAAE,IAAI;QACjB,UAAU,EAAE,KAAK;QACjB,UAAU,EAAE,IAAI,GAAG,EAAE;QACrB,cAAc,EAAE,IAAI;QACpB,gBAAgB,EAAE,IAAI,GAAG,EAAE;QAC3B,kBAAkB,EAAE,CAAC;QACrB,oBAAoB,EAAE,IAAI;QAC1B,mBAAmB,EAAE,KAAK;QAC1B,oBAAoB,EAAE,IAAI,GAAG,EAAE;QAC/B,cAAc,EAAE,KAAK;QACrB,wBAAwB,EAAE,KAAK;KAChC,CAAC;IACF,CAAC,CAAC,UAAU,CAAC,GAAG,KAAK,CAAC;IACtB,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,IAGrC;IACC,MAAM,KAAK,GAAG,SAAS,EAAE,CAAC;IAC1B,IAAI,KAAK,CAAC,WAAW;QAAE,OAAO;IAC9B,KAAK,CAAC,WAAW,GAAG,IAAI,CAAC;IAEzB,MAAM,YAAY,GAChB,IAAI,EAAE,YAAY;QAClB,OAAO,CAAC,GAAG,CAAC,aAAa;QACzB,IAAI,CAAC,OAAO,EAAE,EAAE,WAAW,CAAC,CAAC;IAC/B,MAAM,UAAU,GAAG,IAAI,EAAE,UAAU,IAAI,gBAAgB,CAAC;IAExD,KAAK,CAAC,WAAW,GAAG,WAAW,EAAE;SAC9B,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE;QAChB,KAAK,CAAC,OAAO,GAAG,OAAO,CAAC;IAC1B,CAAC,CAAC;SACD,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;QACtB,OAAO,CAAC,IAAI,CAAC,yCAAyC,EAAE,GAAG,CAAC,CAAC;QAC7D,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC;IACvB,CAAC,CAAC,CAAC;IAEL,MAAM,IAAI,GAAG,GAAS,EAAE;QACtB,QAAQ,CAAC,YAAY,EAAE,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;YACnD,OAAO,CAAC,KAAK,CAAC,mCAAmC,EAAE,GAAG,CAAC,CAAC;QAC1D,CAAC,CAAC,CAAC;IACL,CAAC,CAAC;IAEF,MAAM,MAAM,GAAG,WAAW,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;IAC7C,KAAK,CAAC,cAAc,GAAG,MAAM,CAAC;IAC9B,IAAI,OAAO,MAAM,CAAC,KAAK,KAAK,UAAU;QAAE,MAAM,CAAC,KAAK,EAAE,CAAC;IAEvD,OAAO,CAAC,GAAG,CACT,6CAA6C,UAAU,iBAAiB,YAAY,EAAE,CACvF,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,WAAW;IACxB,MAAM,IAAI,GAAG,CAAC,MAAM,MAAM,CAAC,oBAAoB,CAAC,CAS/C,CAAC;IACF,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;IAChD,OAAO,KAAK,CAAC,aAAa,CAAC,WAAW,EAAE;QACtC,WAAW,EAAE,yDAAyD;QACtE,IAAI,EAAE,KAAK;KACZ,CAAC,CAAC;AACL,CAAC;AAED,KAAK,UAAU,qBAAqB,CAAC,KAAkB;IACrD,IAAI,KAAK,CAAC,oBAAoB,EAAE,CAAC;QAC/B,MAAM,KAAK,CAAC,oBAAoB,CAAC;QACjC,OAAO;IACT,CAAC;IACD,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACvB,IACE,KAAK,CAAC,gBAAgB,CAAC,IAAI,GAAG,CAAC;QAC/B,GAAG,GAAG,KAAK,CAAC,kBAAkB,GAAG,kBAAkB,EACnD,CAAC;QACD,OAAO;IACT,CAAC;IACD,MAAM,MAAM,GAAG,aAAa,CAAC,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IACnD,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,IAAI,CAAC,KAAK,CAAC,cAAc,EAAE,CAAC;YAC1B,KAAK,CAAC,cAAc,GAAG,IAAI,CAAC;YAC5B,OAAO,CAAC,IAAI,CAAC,uEAAuE,CAAC,CAAC;QACxF,CAAC;QACD,OAAO;IACT,CAAC;IACD,KAAK,CAAC,cAAc,GAAG,KAAK,CAAC;IAC7B,MAAM,OAAO,GAAG,cAAc,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAE5C,KAAK,CAAC,oBAAoB,GAAG,CAAC,KAAK,IAAI,EAAE;QACvC,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;YAClD,MAAM,IAAI,GAAG,IAAI,GAAG,EAAqB,CAAC;YAC1C,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;gBACvB,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;oBACb,KAAK,EAAE,CAAC,CAAC,SAAS,IAAI,CAAC;oBACvB,MAAM,EAAE,CAAC,CAAC,UAAU,IAAI,CAAC;oBACzB,SAAS,EAAE,CAAC,CAAC,aAAa,IAAI,CAAC;oBAC/B,UAAU,EAAE,CAAC,CAAC,cAAc,IAAI,CAAC;iBAClC,CAAC,CAAC;YACL,CAAC;YACD,KAAK,CAAC,gBAAgB,GAAG,IAAI,CAAC;YAC9B,KAAK,CAAC,kBAAkB,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YACtC,KAAK,CAAC,wBAAwB,GAAG,KAAK,CAAC;YACvC,IAAI,CAAC,KAAK,CAAC,mBAAmB,EAAE,CAAC;gBAC/B,KAAK,CAAC,mBAAmB,GAAG,IAAI,CAAC;gBACjC,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAC9D,OAAO,CAAC,GAAG,CACT,4CAA4C,IAAI,CAAC,IAAI,iBAAiB,MAAM,GAAG,CAChF,CAAC;YACJ,CAAC;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,KAAK,CAAC,gBAAgB,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,wBAAwB,EAAE,CAAC;gBACzE,KAAK,CAAC,wBAAwB,GAAG,IAAI,CAAC;gBACtC,OAAO,CAAC,IAAI,CAAC,iEAAiE,EAAE,GAAG,CAAC,CAAC;YACvF,CAAC;QACH,CAAC;gBAAS,CAAC;YACT,KAAK,CAAC,oBAAoB,GAAG,IAAI,CAAC;QACpC,CAAC;IACH,CAAC,CAAC,EAAE,CAAC;IACL,MAAM,KAAK,CAAC,oBAAoB,CAAC;AACnC,CAAC;AAED,KAAK,UAAU,QAAQ,CAAC,YAAoB,EAAE,KAAkB;IAC9D,IAAI,KAAK,CAAC,WAAW,EAAE,CAAC;QACtB,MAAM,KAAK,CAAC,WAAW,CAAC;QACxB,KAAK,CAAC,WAAW,GAAG,IAAI,CAAC;IAC3B,CAAC;IACD,IAAI,CAAC,KAAK,CAAC,OAAO;QAAE,OAAO;IAE3B,MAAM,qBAAqB,CAAC,KAAK,CAAC,CAAC;IACnC,IAAI,KAAK,CAAC,gBAAgB,CAAC,IAAI,KAAK,CAAC;QAAE,OAAO;IAE9C,MAAM,SAAS,GAAG,IAAI,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC;IAC/C,IAAI,MAAgB,CAAC;IACrB,IAAI,CAAC;QACH,MAAM,GAAG,MAAM,OAAO,CAAC,SAAS,CAAC,CAAC;IACpC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO;IACT,CAAC;IACD,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,MAAM,eAAe,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,EAAE,UAAU,CAAC,EAAE,KAAK,CAAC,CAAC;IACnE,CAAC;AACH,CAAC;AAED,KAAK,UAAU,eAAe,CAC5B,WAAmB,EACnB,KAAkB;IAElB,IAAI,OAAiB,CAAC;IACtB,IAAI,CAAC;QACH,OAAO,GAAG,MAAM,OAAO,CAAC,WAAW,CAAC,CAAC;IACvC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO;IACT,CAAC;IACD,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,mBAAmB,CAAC;YAAE,SAAS;QACnD,MAAM,eAAe,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,CAAC,EAAE,KAAK,CAAC,CAAC;IACzD,CAAC;AACH,CAAC;AAED,KAAK,UAAU,eAAe,CAAC,IAAY,EAAE,KAAkB;IAC7D,IAAI,IAAmC,CAAC;IACxC,IAAI,CAAC;QACH,MAAM,CAAC,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,CAAC;QAC3B,IAAI,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IACtC,CAAC;IAAC,MAAM,CAAC;QACP,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAC9B,OAAO;IACT,CAAC;IAED,MAAM,IAAI,GAAG,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACxC,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,EAAE;YACzB,MAAM,EAAE,IAAI,CAAC,IAAI;YACjB,KAAK,EAAE,IAAI,CAAC,GAAG;YACf,IAAI,EAAE,IAAI,CAAC,IAAI;SAChB,CAAC,CAAC;QACH,OAAO;IACT,CAAC;IACD,IAAI,IAAI,CAAC,KAAK,KAAK,IAAI,CAAC,GAAG,IAAI,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QACrD,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,EAAE;YACzB,MAAM,EAAE,IAAI,CAAC,IAAI;YACjB,KAAK,EAAE,IAAI,CAAC,GAAG;YACf,IAAI,EAAE,IAAI,CAAC,IAAI;SAChB,CAAC,CAAC;QACH,OAAO;IACT,CAAC;IACD,IAAI,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,MAAM,EAAE,CAAC;QAC9B,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,EAAE;YACzB,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,KAAK,EAAE,IAAI,CAAC,GAAG;YACf,IAAI,EAAE,IAAI,CAAC,IAAI;SAChB,CAAC,CAAC;QACH,OAAO;IACT,CAAC;IAED,MAAM,KAAK,GAAG,MAAM,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;IAC5D,MAAM,QAAQ,GAAG,YAAY,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IAC5C,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,EAAE;QACzB,MAAM,EAAE,IAAI,CAAC,MAAM,GAAG,QAAQ;QAC9B,KAAK,EAAE,IAAI,CAAC,GAAG;QACf,IAAI,EAAE,IAAI,CAAC,IAAI;KAChB,CAAC,CAAC;AACL,CAAC;AAED,SAAS,SAAS,CAAC,IAAY,EAAE,KAAa,EAAE,GAAW;IACzD,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,KAAK,GAAa,EAAE,CAAC;QAC3B,MAAM,MAAM,GAAG,gBAAgB,CAAC,IAAI,EAAE;YACpC,KAAK;YACL,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,GAAG,CAAC,CAAC;YAC7B,QAAQ,EAAE,MAAM;SACjB,CAAC,CAAC;QACH,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAsB,EAAE,EAAE;YAC3C,KAAK,CAAC,IAAI,CAAC,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;QACzE,CAAC,CAAC,CAAC;QACH,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QAChD,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAC7B,CAAC,CAAC,CAAC;AACL,CAAC;AAED,SAAS,YAAY,CAAC,KAAa,EAAE,KAAkB;IACrD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,CAAC,CAAC;IACjC,MAAM,WAAW,GAAG,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;IAC5C,IAAI,WAAW,KAAK,CAAC,CAAC;QAAE,OAAO,CAAC,CAAC;IAEjC,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACtD,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC;YAAE,SAAS;QAC5D,IAAI,MAAe,CAAC;QACpB,IAAI,CAAC;YACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC5B,CAAC;QAAC,MAAM,CAAC;YACP,SAAS;QACX,CAAC;QACD,aAAa,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IAC/B,CAAC;IACD,OAAO,WAAW,GAAG,CAAC,CAAC;AACzB,CAAC;AAED,SAAS,aAAa,CAAC,KAAc,EAAE,KAAkB;IACvD,IAAI,CAAC,KAAK,CAAC,OAAO,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO;IAC/C,IAAI,KAAK,CAAC,IAAI,KAAK,iBAAiB;QAAE,OAAO;IAC7C,IAAI,KAAK,CAAC,QAAQ,KAAK,gBAAgB;QAAE,OAAO;IAChD,IAAI,OAAO,KAAK,CAAC,OAAO,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO;IAC5E,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC;IAE9B,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC;IACxB,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;QAAE,OAAO;IAC5B,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;IACzB,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO;IAE7B,MAAM,IAAI,GAAG,KAAK,CAAC,gBAAgB,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IACjD,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,IAAI,CAAC,KAAK,CAAC,oBAAoB,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;YAC7C,KAAK,CAAC,oBAAoB,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YACxC,OAAO,CAAC,IAAI,CACV,+CAA+C,OAAO,gEAAgE,CACvH,CAAC;QACJ,CAAC;QACD,OAAO;IACT,CAAC;IAED,MAAM,KAAK,GAAG,YAAY,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACxC,MAAM,MAAM,GAAG,YAAY,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAC1C,MAAM,SAAS,GAAG,YAAY,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;IAChD,MAAM,UAAU,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC;IAExC,MAAM,OAAO,GACX,CAAC,IAAI,CAAC,KAAK,GAAG,KAAK;QACjB,IAAI,CAAC,MAAM,GAAG,MAAM;QACpB,IAAI,CAAC,SAAS,GAAG,SAAS;QAC1B,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;QAC/B,SAAS,CAAC;IAEZ,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,OAAO,IAAI,CAAC;QAAE,OAAO;IAEtD,MAAM,KAAK,GAA2B;QACpC,mBAAmB,EAAE,gBAAgB;QACrC,gBAAgB,EAAE,OAAO;KAC1B,CAAC;IACF,MAAM,OAAO,GAAG,0BAA0B,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;IAC7D,IAAI,OAAO;QAAE,KAAK,CAAC,kBAAkB,CAAC,GAAG,OAAO,CAAC;IAEjD,IAAI,CAAC;QACH,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;QAClC,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE,CAAC;YACtB,KAAK,CAAC,UAAU,GAAG,IAAI,CAAC;YACxB,OAAO,CAAC,GAAG,CACT,qCAAqC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,cAAc,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,WAAW,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,CAAC,EAAE,CAChK,CAAC;QACJ,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,2CAA2C,EAAE,GAAG,CAAC,CAAC;IAClE,CAAC;AACH,CAAC;AAED,SAAS,cAAc,CAAC,IAA6B;IACnD,MAAM,EAAE,GAAG,IAAI,CAAC,WAAW,CAAC;IAC5B,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;QAAE,OAAO,CAAC,CAAC;IAC5B,MAAM,GAAG,GAAG,EAAE,CAAC,aAAa,CAAC;IAC7B,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC;QAAE,OAAO,CAAC,CAAC;IAC7B,OAAO,YAAY,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;AACtC,CAAC;AAED,SAAS,0BAA0B,CAAC,UAAmB;IACrD,IAAI,OAAO,UAAU,KAAK,QAAQ;QAAE,OAAO,SAAS,CAAC;IACrD,kDAAkD;IAClD,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACpC,IAAI,KAAK,CAAC,MAAM,IAAI,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,OAAO,EAAE,CAAC;QAC9C,MAAM,EAAE,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACpB,OAAO,OAAO,EAAE,KAAK,QAAQ,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;IAClE,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAS,QAAQ,CAAC,CAAU;IAC1B,OAAO,CAAC,KAAK,IAAI,IAAI,OAAO,CAAC,KAAK,QAAQ,CAAC;AAC7C,CAAC;AAED,SAAS,YAAY,CAAC,CAAU;IAC9B,OAAO,OAAO,CAAC,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACvE,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAkB,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAIrE;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,QAAA,MAAM,KAAK,EAAE,WAkCZ,CAAC;AAEF,eAAe,KAAK,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAkB,WAAW,EAAE,MAAM,mBAAmB,CAAC;AASrE;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,QAAA,MAAM,KAAK,EAAE,WAkCZ,CAAC;AAEF,eAAe,KAAK,CAAC"}
package/dist/index.js CHANGED
@@ -1,4 +1,8 @@
1
1
  import { API_KEY_ENV_VAR, BASE_URL_ENV_VAR, PROVIDER_ID, PROVIDER_LABEL, buildCatalogRows, buildProvider, resolveApiKey, resolveBaseUrl, } from "./models.js";
2
+ import { startCostMetricPoller } from "./cost-metric.js";
3
+ // See cost-metric.ts. Idempotent across both entry files via
4
+ // globalThis-stored state — whichever module openclaw loads first wins.
5
+ startCostMetricPoller();
2
6
  const PLUGIN_ID = "runware-openclaw-provider";
3
7
  /**
4
8
  * Plugin entry that openclaw's plugin loader invokes after `npm install`-ing
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,gBAAgB,EAChB,WAAW,EACX,cAAc,EACd,gBAAgB,EAChB,aAAa,EACb,aAAa,EACb,cAAc,GACf,MAAM,aAAa,CAAC;AAGrB,MAAM,SAAS,GAAG,2BAA2B,CAAC;AAE9C;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,KAAK,GAAgB;IACzB,EAAE,EAAE,SAAS;IACb,IAAI,EAAE,cAAc;IACpB,WAAW,EACT,yGAAyG;IAE3G,QAAQ,CAAC,GAAG;QACV,GAAG,CAAC,gBAAgB,CAAC;YACnB,EAAE,EAAE,WAAW;YACf,KAAK,EAAE,cAAc;YACrB,QAAQ,EAAE,yBAAyB;YACnC,OAAO,EAAE,CAAC,eAAe,EAAE,gBAAgB,CAAC;YAC5C,IAAI,EAAE,EAAE;YACR,OAAO,EAAE;gBACP,KAAK,EAAE,QAAQ;gBACf,GAAG,EAAE,KAAK,EAAE,GAAmB,EAAE,EAAE;oBACjC,MAAM,MAAM,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC;oBAClC,IAAI,CAAC,MAAM;wBAAE,OAAO,IAAI,CAAC;oBACzB,MAAM,QAAQ,GAAG,MAAM,aAAa,CAAC,MAAM,EAAE,cAAc,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;oBACtE,OAAO,EAAE,QAAQ,EAAE,CAAC;gBACtB,CAAC;aACF;SACF,CAAC,CAAC;QAEH,GAAG,CAAC,4BAA4B,CAAC;YAC/B,QAAQ,EAAE,WAAW;YACrB,KAAK,EAAE,CAAC,MAAM,CAAC;YACf,WAAW,EAAE,KAAK,EAAE,GAAmB,EAAE,EAAE;gBACzC,MAAM,MAAM,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC;gBAClC,IAAI,CAAC,MAAM;oBAAE,OAAO,IAAI,CAAC;gBACzB,OAAO,gBAAgB,CAAC,MAAM,EAAE,cAAc,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;YAC3D,CAAC;SACF,CAAC,CAAC;IACL,CAAC;CACF,CAAC;AAEF,eAAe,KAAK,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,gBAAgB,EAChB,WAAW,EACX,cAAc,EACd,gBAAgB,EAChB,aAAa,EACb,aAAa,EACb,cAAc,GACf,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AAEzD,6DAA6D;AAC7D,wEAAwE;AACxE,qBAAqB,EAAE,CAAC;AAExB,MAAM,SAAS,GAAG,2BAA2B,CAAC;AAE9C;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,KAAK,GAAgB;IACzB,EAAE,EAAE,SAAS;IACb,IAAI,EAAE,cAAc;IACpB,WAAW,EACT,yGAAyG;IAE3G,QAAQ,CAAC,GAAG;QACV,GAAG,CAAC,gBAAgB,CAAC;YACnB,EAAE,EAAE,WAAW;YACf,KAAK,EAAE,cAAc;YACrB,QAAQ,EAAE,yBAAyB;YACnC,OAAO,EAAE,CAAC,eAAe,EAAE,gBAAgB,CAAC;YAC5C,IAAI,EAAE,EAAE;YACR,OAAO,EAAE;gBACP,KAAK,EAAE,QAAQ;gBACf,GAAG,EAAE,KAAK,EAAE,GAAmB,EAAE,EAAE;oBACjC,MAAM,MAAM,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC;oBAClC,IAAI,CAAC,MAAM;wBAAE,OAAO,IAAI,CAAC;oBACzB,MAAM,QAAQ,GAAG,MAAM,aAAa,CAAC,MAAM,EAAE,cAAc,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;oBACtE,OAAO,EAAE,QAAQ,EAAE,CAAC;gBACtB,CAAC;aACF;SACF,CAAC,CAAC;QAEH,GAAG,CAAC,4BAA4B,CAAC;YAC/B,QAAQ,EAAE,WAAW;YACrB,KAAK,EAAE,CAAC,MAAM,CAAC;YACf,WAAW,EAAE,KAAK,EAAE,GAAmB,EAAE,EAAE;gBACzC,MAAM,MAAM,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC;gBAClC,IAAI,CAAC,MAAM;oBAAE,OAAO,IAAI,CAAC;gBACzB,OAAO,gBAAgB,CAAC,MAAM,EAAE,cAAc,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;YAC3D,CAAC;SACF,CAAC,CAAC;IACL,CAAC;CACF,CAAC;AAEF,eAAe,KAAK,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"provider-discovery.d.ts","sourceRoot":"","sources":["../src/provider-discovery.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,gBAAgB,EAMjB,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEjD;;;;;;;;;;;;;;GAcG;AAEH,UAAU,YAAY;IACpB,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;IACzC,qBAAqB,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK;QAAE,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CACrE;AAYD,iBAAe,iBAAiB,CAAC,GAAG,EAAE,YAAY,GAAG,OAAO,CAAC;IAAE,QAAQ,EAAE,aAAa,CAAA;CAAE,CAAC,CAUxF;AAED,QAAA,MAAM,wBAAwB;;;;;;;;;;CAU7B,CAAC;AAEF,eAAe,wBAAwB,CAAC;AACxC,OAAO,EAAE,gBAAgB,EAAE,CAAC"}
1
+ {"version":3,"file":"provider-discovery.d.ts","sourceRoot":"","sources":["../src/provider-discovery.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,gBAAgB,EAMjB,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAUjD;;;;;;;;;;;;;;GAcG;AAEH,UAAU,YAAY;IACpB,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;IACzC,qBAAqB,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK;QAAE,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CACrE;AAYD,iBAAe,iBAAiB,CAAC,GAAG,EAAE,YAAY,GAAG,OAAO,CAAC;IAAE,QAAQ,EAAE,aAAa,CAAA;CAAE,CAAC,CAUxF;AAED,QAAA,MAAM,wBAAwB;;;;;;;;;;CAU7B,CAAC;AAEF,eAAe,wBAAwB,CAAC;AACxC,OAAO,EAAE,gBAAgB,EAAE,CAAC"}
@@ -1,4 +1,11 @@
1
1
  import { API_KEY_ENV_VAR, BASE_URL_ENV_VAR, DEFAULT_BASE_URL, PROVIDER_ID, PROVIDER_LABEL, buildProvider, resolveApiKey, resolveBaseUrl, } from "./models.js";
2
+ import { startCostMetricPoller } from "./cost-metric.js";
3
+ // Emit `openclaw.cost.usd` OpenTelemetry counter from runware transcript
4
+ // entries. Compensates for openclaw's broken diagnostic-path pricing
5
+ // resolver (cachedPricing Map never sees runware pricing). See
6
+ // cost-metric.ts for the full rationale. Idempotent: also called from
7
+ // index.ts, second call is a no-op.
8
+ startCostMetricPoller();
2
9
  function emptyProvider(baseUrl) {
3
10
  return {
4
11
  baseUrl,
@@ -1 +1 @@
1
- {"version":3,"file":"provider-discovery.js","sourceRoot":"","sources":["../src/provider-discovery.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,gBAAgB,EAChB,gBAAgB,EAChB,WAAW,EACX,cAAc,EACd,aAAa,EACb,aAAa,EACb,cAAc,GACf,MAAM,aAAa,CAAC;AAwBrB,SAAS,aAAa,CAAC,OAAe;IACpC,OAAO;QACL,OAAO;QACP,MAAM,EAAE,EAAE;QACV,GAAG,EAAE,oBAAoB;QACzB,cAAc,EAAE,GAAG;QACnB,MAAM,EAAE,EAAE;KACX,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,iBAAiB,CAAC,GAAiB;IAChD,MAAM,OAAO,GAAG,cAAc,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACxC,MAAM,MAAM,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC;IAClC,uEAAuE;IACvE,0EAA0E;IAC1E,uEAAuE;IACvE,wEAAwE;IACxE,yDAAyD;IACzD,IAAI,CAAC,MAAM;QAAE,OAAO,EAAE,QAAQ,EAAE,aAAa,CAAC,OAAO,CAAC,EAAE,CAAC;IACzD,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;AAC5D,CAAC;AAED,MAAM,wBAAwB,GAAG;IAC/B,EAAE,EAAE,WAAW;IACf,KAAK,EAAE,cAAc;IACrB,QAAQ,EAAE,yBAAyB;IACnC,OAAO,EAAE,CAAC,eAAe,EAAE,gBAAgB,CAAC;IAC5C,IAAI,EAAE,EAAE;IACR,OAAO,EAAE;QACP,KAAK,EAAE,MAAe;QACtB,GAAG,EAAE,iBAAiB;KACvB;CACF,CAAC;AAEF,eAAe,wBAAwB,CAAC;AACxC,OAAO,EAAE,gBAAgB,EAAE,CAAC"}
1
+ {"version":3,"file":"provider-discovery.js","sourceRoot":"","sources":["../src/provider-discovery.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,gBAAgB,EAChB,gBAAgB,EAChB,WAAW,EACX,cAAc,EACd,aAAa,EACb,aAAa,EACb,cAAc,GACf,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AAEzD,yEAAyE;AACzE,qEAAqE;AACrE,+DAA+D;AAC/D,sEAAsE;AACtE,oCAAoC;AACpC,qBAAqB,EAAE,CAAC;AAuBxB,SAAS,aAAa,CAAC,OAAe;IACpC,OAAO;QACL,OAAO;QACP,MAAM,EAAE,EAAE;QACV,GAAG,EAAE,oBAAoB;QACzB,cAAc,EAAE,GAAG;QACnB,MAAM,EAAE,EAAE;KACX,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,iBAAiB,CAAC,GAAiB;IAChD,MAAM,OAAO,GAAG,cAAc,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACxC,MAAM,MAAM,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC;IAClC,uEAAuE;IACvE,0EAA0E;IAC1E,uEAAuE;IACvE,wEAAwE;IACxE,yDAAyD;IACzD,IAAI,CAAC,MAAM;QAAE,OAAO,EAAE,QAAQ,EAAE,aAAa,CAAC,OAAO,CAAC,EAAE,CAAC;IACzD,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;AAC5D,CAAC;AAED,MAAM,wBAAwB,GAAG;IAC/B,EAAE,EAAE,WAAW;IACf,KAAK,EAAE,cAAc;IACrB,QAAQ,EAAE,yBAAyB;IACnC,OAAO,EAAE,CAAC,eAAe,EAAE,gBAAgB,CAAC;IAC5C,IAAI,EAAE,EAAE;IACR,OAAO,EAAE;QACP,KAAK,EAAE,MAAe;QACtB,GAAG,EAAE,iBAAiB;KACvB;CACF,CAAC;AAEF,eAAe,wBAAwB,CAAC;AACxC,OAAO,EAAE,gBAAgB,EAAE,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@teith/openclaw-runware-provider",
3
- "version": "0.3.3",
3
+ "version": "0.3.5",
4
4
  "description": "OpenClaw provider plugin for Runware — unified OpenAI-compatible access to Claude, GPT, Gemini, Qwen, GLM, MiniMax, Kimi, and Gemma.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -54,6 +54,9 @@
54
54
  "engines": {
55
55
  "node": ">=20"
56
56
  },
57
+ "dependencies": {
58
+ "@opentelemetry/api": "^1.9.0"
59
+ },
57
60
  "devDependencies": {
58
61
  "@types/node": "^22.0.0",
59
62
  "typescript": "^5.6.0",