@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.
- package/dist/cost-metric.d.ts +58 -0
- package/dist/cost-metric.d.ts.map +1 -0
- package/dist/cost-metric.js +373 -0
- package/dist/cost-metric.js.map +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/provider-discovery.d.ts.map +1 -1
- package/dist/provider-discovery.js +7 -0
- package/dist/provider-discovery.js.map +1 -1
- package/package.json +4 -1
|
@@ -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":"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"}
|
package/dist/index.d.ts.map
CHANGED
|
@@ -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;
|
|
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;
|
|
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;
|
|
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;
|
|
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
|
+
"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",
|