@teith/openclaw-runware-provider 0.3.2 → 0.3.4
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/catalog.d.ts +1 -0
- package/dist/catalog.d.ts.map +1 -1
- package/dist/catalog.js +23 -10
- package/dist/catalog.js.map +1 -1
- package/dist/cost-metric.d.ts +81 -0
- package/dist/cost-metric.d.ts.map +1 -0
- package/dist/cost-metric.js +334 -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/models.d.ts +3 -2
- package/dist/models.d.ts.map +1 -1
- package/dist/models.js +5 -2
- package/dist/models.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
package/dist/catalog.d.ts
CHANGED
|
@@ -7,6 +7,7 @@ export interface RunwareModel {
|
|
|
7
7
|
outputCost?: number;
|
|
8
8
|
cacheReadCost?: number;
|
|
9
9
|
cacheWriteCost?: number;
|
|
10
|
+
inputModalities?: string[];
|
|
10
11
|
}
|
|
11
12
|
export declare function fetchModels(baseUrl: string, apiKey: string): Promise<RunwareModel[]>;
|
|
12
13
|
export declare function resetCache(): void;
|
package/dist/catalog.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../src/catalog.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../src/catalog.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;CAC5B;AAcD,wBAAsB,WAAW,CAC/B,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,YAAY,EAAE,CAAC,CAsBzB;AAmED,wBAAgB,UAAU,IAAI,IAAI,CAGjC"}
|
package/dist/catalog.js
CHANGED
|
@@ -64,17 +64,30 @@ function parseRunwareModel(raw) {
|
|
|
64
64
|
if (typeof m.max_output_tokens === "number" && m.max_output_tokens > 0) {
|
|
65
65
|
parsed.maxOutputTokens = m.max_output_tokens;
|
|
66
66
|
}
|
|
67
|
-
if (typeof m.
|
|
68
|
-
|
|
67
|
+
if (m.pricing && typeof m.pricing === "object") {
|
|
68
|
+
const p = m.pricing;
|
|
69
|
+
const perMillion = (key) => {
|
|
70
|
+
const raw = typeof p[key] === "string" ? parseFloat(p[key])
|
|
71
|
+
: typeof p[key] === "number" ? p[key]
|
|
72
|
+
: NaN;
|
|
73
|
+
return Number.isFinite(raw) && raw >= 0 ? raw * 1_000_000 : undefined;
|
|
74
|
+
};
|
|
75
|
+
const input = perMillion("prompt");
|
|
76
|
+
const output = perMillion("completion");
|
|
77
|
+
const cacheRead = perMillion("input_cache_read");
|
|
78
|
+
const cacheWrite = perMillion("input_cache_write");
|
|
79
|
+
if (input !== undefined)
|
|
80
|
+
parsed.inputCost = input;
|
|
81
|
+
if (output !== undefined)
|
|
82
|
+
parsed.outputCost = output;
|
|
83
|
+
if (cacheRead !== undefined)
|
|
84
|
+
parsed.cacheReadCost = cacheRead;
|
|
85
|
+
if (cacheWrite !== undefined)
|
|
86
|
+
parsed.cacheWriteCost = cacheWrite;
|
|
69
87
|
}
|
|
70
|
-
if (
|
|
71
|
-
parsed.
|
|
72
|
-
|
|
73
|
-
if (typeof m.cache_read_cost === "number" && m.cache_read_cost >= 0) {
|
|
74
|
-
parsed.cacheReadCost = m.cache_read_cost;
|
|
75
|
-
}
|
|
76
|
-
if (typeof m.cache_write_cost === "number" && m.cache_write_cost >= 0) {
|
|
77
|
-
parsed.cacheWriteCost = m.cache_write_cost;
|
|
88
|
+
if (Array.isArray(m.input_modalities)) {
|
|
89
|
+
parsed.inputModalities = m.input_modalities
|
|
90
|
+
.filter((v) => typeof v === "string" && v.length > 0);
|
|
78
91
|
}
|
|
79
92
|
return parsed;
|
|
80
93
|
}
|
package/dist/catalog.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"catalog.js","sourceRoot":"","sources":["../src/catalog.ts"],"names":[],"mappings":"AAAA,MAAM,YAAY,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;AACnC,MAAM,gBAAgB,GAAG,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"catalog.js","sourceRoot":"","sources":["../src/catalog.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Emits `openclaw.cost.usd` OpenTelemetry counter for runware completions.
|
|
3
|
+
*
|
|
4
|
+
* Why this file exists
|
|
5
|
+
* --------------------
|
|
6
|
+
* OpenClaw 2026.6.1 has two cost-computation paths with different data
|
|
7
|
+
* sources:
|
|
8
|
+
*
|
|
9
|
+
* Completion path (works) — openai-completions runtime calls
|
|
10
|
+
* `calculateCost(model, usage)` with the live `model` object returned
|
|
11
|
+
* by this plugin's `catalog.run`. `model.cost` is populated from
|
|
12
|
+
* `/v1/models`. Result is written into transcript JSONL as
|
|
13
|
+
* `usage.cost`. Usage UI reads from there.
|
|
14
|
+
*
|
|
15
|
+
* Diagnostic path (broken) — `agent-runner` emits `model.usage`
|
|
16
|
+
* diagnostic events with `costUsd = estimateUsageCost({ usage, cost:
|
|
17
|
+
* resolveModelCostConfig(provider, model, config) })`. That resolver
|
|
18
|
+
* reads ONLY from:
|
|
19
|
+
* • `models.json` cost index
|
|
20
|
+
* • `openclaw.json` `models.providers.*.models[].cost`
|
|
21
|
+
* • `cachedPricing` Map (seeded from manifest `modelCatalog` and
|
|
22
|
+
* upstream OpenRouter/LiteLLM catalogs)
|
|
23
|
+
* None of those carry runware pricing — pricing flows through the
|
|
24
|
+
* plugin's runtime `catalog.run`, which is invisible to this resolver.
|
|
25
|
+
* So `costUsd` is undefined, the diagnostics-otel handler's
|
|
26
|
+
* `if (evt.costUsd) costCounter.add(...)` guard is falsy, and the
|
|
27
|
+
* `openclaw_cost_usd_total` counter stays at zero.
|
|
28
|
+
*
|
|
29
|
+
* What this file does
|
|
30
|
+
* -------------------
|
|
31
|
+
* Tails session transcripts (`~/.openclaw/agents/<id>/sessions/*.jsonl`),
|
|
32
|
+
* which already contain `usage.cost.total` because the completion path
|
|
33
|
+
* filled them in. Parses new entries on a 2s tick, filters to
|
|
34
|
+
* `provider === "runware"`, and writes to the same global OTel counter
|
|
35
|
+
* `openclaw.cost.usd` that diagnostics-otel tried (and failed) to write
|
|
36
|
+
* to. The OTel API stores its MeterProvider on a globalThis symbol slot
|
|
37
|
+
* so plugin-side `getMeter(...).createCounter("openclaw.cost.usd", ...)`
|
|
38
|
+
* shares the MeterProvider that diagnostics-otel registered at gateway
|
|
39
|
+
* start. Counter writes from both sides land on the same
|
|
40
|
+
* `(name, attributes)` time series in OTLP → Prometheus → GMP.
|
|
41
|
+
*
|
|
42
|
+
* Why polling and not a hook
|
|
43
|
+
* --------------------------
|
|
44
|
+
* `llm_output` and `agent_end` carry usage, but openclaw blocks them for
|
|
45
|
+
* non-bundled plugins unless `plugins.entries.<id>.hooks
|
|
46
|
+
* .allowConversationAccess: true` is set in openclaw.json — i.e. in the
|
|
47
|
+
* manager. `model_call_ended` is bundled-accessible but only carries
|
|
48
|
+
* sanitized metadata (no usage). `wrapStreamFn` is a provider-runtime
|
|
49
|
+
* hook on `registerProvider` but `register(api)` is not invoked for
|
|
50
|
+
* external plugins in 2026.5.x and behavior is unverified in 2026.6.1.
|
|
51
|
+
* Tailing the transcript file is the one path that does not depend on
|
|
52
|
+
* any of those (the transcripts are written by the completion path
|
|
53
|
+
* regardless of hooks).
|
|
54
|
+
*
|
|
55
|
+
* Double-counting safety
|
|
56
|
+
* ----------------------
|
|
57
|
+
* On startup the poller takes the current size of every transcript
|
|
58
|
+
* file as the initial offset — existing entries are assumed already
|
|
59
|
+
* accounted for by whatever was running before. Only bytes appended
|
|
60
|
+
* after startup emit metrics. Gateway restart resets all offsets, which
|
|
61
|
+
* is the correct behavior for a process-scoped counter (Prometheus
|
|
62
|
+
* `rate()` handles counter resets).
|
|
63
|
+
*
|
|
64
|
+
* If openclaw eventually fixes the diagnostic path so that
|
|
65
|
+
* `evt.costUsd` is populated for runware, both writers will increment
|
|
66
|
+
* the same series and the metric will double for runware. At that point
|
|
67
|
+
* delete this module. (We do not attempt to detect that case at runtime
|
|
68
|
+
* because diagnostics-otel does not expose its emit-or-skip decision to
|
|
69
|
+
* other plugins.)
|
|
70
|
+
*/
|
|
71
|
+
/**
|
|
72
|
+
* Idempotent. Safe to call from multiple plugin entry files; only the
|
|
73
|
+
* first call starts the interval, subsequent calls return immediately.
|
|
74
|
+
* Survives openclaw plugin hot-reload because state lives on
|
|
75
|
+
* `globalThis`.
|
|
76
|
+
*/
|
|
77
|
+
export declare function startCostMetricPoller(opts?: {
|
|
78
|
+
openclawHome?: string;
|
|
79
|
+
intervalMs?: number;
|
|
80
|
+
}): void;
|
|
81
|
+
//# 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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqEG;AAgDH;;;;;GAKG;AACH,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,334 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Emits `openclaw.cost.usd` OpenTelemetry counter for runware completions.
|
|
3
|
+
*
|
|
4
|
+
* Why this file exists
|
|
5
|
+
* --------------------
|
|
6
|
+
* OpenClaw 2026.6.1 has two cost-computation paths with different data
|
|
7
|
+
* sources:
|
|
8
|
+
*
|
|
9
|
+
* Completion path (works) — openai-completions runtime calls
|
|
10
|
+
* `calculateCost(model, usage)` with the live `model` object returned
|
|
11
|
+
* by this plugin's `catalog.run`. `model.cost` is populated from
|
|
12
|
+
* `/v1/models`. Result is written into transcript JSONL as
|
|
13
|
+
* `usage.cost`. Usage UI reads from there.
|
|
14
|
+
*
|
|
15
|
+
* Diagnostic path (broken) — `agent-runner` emits `model.usage`
|
|
16
|
+
* diagnostic events with `costUsd = estimateUsageCost({ usage, cost:
|
|
17
|
+
* resolveModelCostConfig(provider, model, config) })`. That resolver
|
|
18
|
+
* reads ONLY from:
|
|
19
|
+
* • `models.json` cost index
|
|
20
|
+
* • `openclaw.json` `models.providers.*.models[].cost`
|
|
21
|
+
* • `cachedPricing` Map (seeded from manifest `modelCatalog` and
|
|
22
|
+
* upstream OpenRouter/LiteLLM catalogs)
|
|
23
|
+
* None of those carry runware pricing — pricing flows through the
|
|
24
|
+
* plugin's runtime `catalog.run`, which is invisible to this resolver.
|
|
25
|
+
* So `costUsd` is undefined, the diagnostics-otel handler's
|
|
26
|
+
* `if (evt.costUsd) costCounter.add(...)` guard is falsy, and the
|
|
27
|
+
* `openclaw_cost_usd_total` counter stays at zero.
|
|
28
|
+
*
|
|
29
|
+
* What this file does
|
|
30
|
+
* -------------------
|
|
31
|
+
* Tails session transcripts (`~/.openclaw/agents/<id>/sessions/*.jsonl`),
|
|
32
|
+
* which already contain `usage.cost.total` because the completion path
|
|
33
|
+
* filled them in. Parses new entries on a 2s tick, filters to
|
|
34
|
+
* `provider === "runware"`, and writes to the same global OTel counter
|
|
35
|
+
* `openclaw.cost.usd` that diagnostics-otel tried (and failed) to write
|
|
36
|
+
* to. The OTel API stores its MeterProvider on a globalThis symbol slot
|
|
37
|
+
* so plugin-side `getMeter(...).createCounter("openclaw.cost.usd", ...)`
|
|
38
|
+
* shares the MeterProvider that diagnostics-otel registered at gateway
|
|
39
|
+
* start. Counter writes from both sides land on the same
|
|
40
|
+
* `(name, attributes)` time series in OTLP → Prometheus → GMP.
|
|
41
|
+
*
|
|
42
|
+
* Why polling and not a hook
|
|
43
|
+
* --------------------------
|
|
44
|
+
* `llm_output` and `agent_end` carry usage, but openclaw blocks them for
|
|
45
|
+
* non-bundled plugins unless `plugins.entries.<id>.hooks
|
|
46
|
+
* .allowConversationAccess: true` is set in openclaw.json — i.e. in the
|
|
47
|
+
* manager. `model_call_ended` is bundled-accessible but only carries
|
|
48
|
+
* sanitized metadata (no usage). `wrapStreamFn` is a provider-runtime
|
|
49
|
+
* hook on `registerProvider` but `register(api)` is not invoked for
|
|
50
|
+
* external plugins in 2026.5.x and behavior is unverified in 2026.6.1.
|
|
51
|
+
* Tailing the transcript file is the one path that does not depend on
|
|
52
|
+
* any of those (the transcripts are written by the completion path
|
|
53
|
+
* regardless of hooks).
|
|
54
|
+
*
|
|
55
|
+
* Double-counting safety
|
|
56
|
+
* ----------------------
|
|
57
|
+
* On startup the poller takes the current size of every transcript
|
|
58
|
+
* file as the initial offset — existing entries are assumed already
|
|
59
|
+
* accounted for by whatever was running before. Only bytes appended
|
|
60
|
+
* after startup emit metrics. Gateway restart resets all offsets, which
|
|
61
|
+
* is the correct behavior for a process-scoped counter (Prometheus
|
|
62
|
+
* `rate()` handles counter resets).
|
|
63
|
+
*
|
|
64
|
+
* If openclaw eventually fixes the diagnostic path so that
|
|
65
|
+
* `evt.costUsd` is populated for runware, both writers will increment
|
|
66
|
+
* the same series and the metric will double for runware. At that point
|
|
67
|
+
* delete this module. (We do not attempt to detect that case at runtime
|
|
68
|
+
* because diagnostics-otel does not expose its emit-or-skip decision to
|
|
69
|
+
* other plugins.)
|
|
70
|
+
*/
|
|
71
|
+
import { createReadStream } from "node:fs";
|
|
72
|
+
import { readdir, stat } from "node:fs/promises";
|
|
73
|
+
import { homedir } from "node:os";
|
|
74
|
+
import { join } from "node:path";
|
|
75
|
+
const GLOBAL_KEY = "__runware_openclaw_cost_metric__";
|
|
76
|
+
const POLL_INTERVAL_MS = 2000;
|
|
77
|
+
const RUNWARE_PROVIDER = "runware";
|
|
78
|
+
const METER_NAME = "runware-openclaw-provider";
|
|
79
|
+
const METRIC_NAME = "openclaw.cost.usd";
|
|
80
|
+
function loadState() {
|
|
81
|
+
const g = globalThis;
|
|
82
|
+
const existing = g[GLOBAL_KEY];
|
|
83
|
+
if (existing)
|
|
84
|
+
return existing;
|
|
85
|
+
const fresh = {
|
|
86
|
+
initialized: false,
|
|
87
|
+
counter: null,
|
|
88
|
+
counterInit: null,
|
|
89
|
+
emittedAny: false,
|
|
90
|
+
fileStates: new Map(),
|
|
91
|
+
intervalHandle: null,
|
|
92
|
+
};
|
|
93
|
+
g[GLOBAL_KEY] = fresh;
|
|
94
|
+
return fresh;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Idempotent. Safe to call from multiple plugin entry files; only the
|
|
98
|
+
* first call starts the interval, subsequent calls return immediately.
|
|
99
|
+
* Survives openclaw plugin hot-reload because state lives on
|
|
100
|
+
* `globalThis`.
|
|
101
|
+
*/
|
|
102
|
+
export function startCostMetricPoller(opts) {
|
|
103
|
+
const state = loadState();
|
|
104
|
+
if (state.initialized)
|
|
105
|
+
return;
|
|
106
|
+
state.initialized = true;
|
|
107
|
+
const openclawHome = opts?.openclawHome ??
|
|
108
|
+
process.env.OPENCLAW_HOME ??
|
|
109
|
+
join(homedir(), ".openclaw");
|
|
110
|
+
const intervalMs = opts?.intervalMs ?? POLL_INTERVAL_MS;
|
|
111
|
+
state.counterInit = initCounter()
|
|
112
|
+
.then((counter) => {
|
|
113
|
+
state.counter = counter;
|
|
114
|
+
})
|
|
115
|
+
.catch((err) => {
|
|
116
|
+
console.warn("[runware-cost-metric] OTel init failed:", err);
|
|
117
|
+
state.counter = null;
|
|
118
|
+
});
|
|
119
|
+
const tick = () => {
|
|
120
|
+
pollOnce(openclawHome, state).catch((err) => {
|
|
121
|
+
console.error("[runware-cost-metric] poll error:", err);
|
|
122
|
+
});
|
|
123
|
+
};
|
|
124
|
+
const handle = setInterval(tick, intervalMs);
|
|
125
|
+
state.intervalHandle = handle;
|
|
126
|
+
if (typeof handle.unref === "function")
|
|
127
|
+
handle.unref();
|
|
128
|
+
console.log(`[runware-cost-metric] started, intervalMs=${intervalMs} openclawHome=${openclawHome}`);
|
|
129
|
+
}
|
|
130
|
+
async function initCounter() {
|
|
131
|
+
// Dynamic import so a missing @opentelemetry/api doesn't break the
|
|
132
|
+
// plugin entry. Typed structurally — we don't import OTel types
|
|
133
|
+
// statically because verbatimModuleSyntax disallows type-only imports
|
|
134
|
+
// here without `import type`, and the dynamic shape is all we need.
|
|
135
|
+
const otel = (await import("@opentelemetry/api"));
|
|
136
|
+
const meter = otel.metrics.getMeter(METER_NAME);
|
|
137
|
+
return meter.createCounter(METRIC_NAME, {
|
|
138
|
+
description: "Estimated model cost in USD (emitted by runware plugin)",
|
|
139
|
+
unit: "USD",
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
async function pollOnce(openclawHome, state) {
|
|
143
|
+
if (state.counterInit) {
|
|
144
|
+
await state.counterInit;
|
|
145
|
+
state.counterInit = null;
|
|
146
|
+
}
|
|
147
|
+
if (!state.counter)
|
|
148
|
+
return;
|
|
149
|
+
const agentsDir = join(openclawHome, "agents");
|
|
150
|
+
let agents;
|
|
151
|
+
try {
|
|
152
|
+
agents = await readdir(agentsDir);
|
|
153
|
+
}
|
|
154
|
+
catch {
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
for (const agent of agents) {
|
|
158
|
+
await pollSessionsDir(join(agentsDir, agent, "sessions"), state);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
async function pollSessionsDir(sessionsDir, state) {
|
|
162
|
+
let entries;
|
|
163
|
+
try {
|
|
164
|
+
entries = await readdir(sessionsDir);
|
|
165
|
+
}
|
|
166
|
+
catch {
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
for (const entry of entries) {
|
|
170
|
+
if (!entry.endsWith(".jsonl"))
|
|
171
|
+
continue;
|
|
172
|
+
await pollSessionFile(join(sessionsDir, entry), state);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
async function pollSessionFile(path, state) {
|
|
176
|
+
let info;
|
|
177
|
+
try {
|
|
178
|
+
const s = await stat(path);
|
|
179
|
+
info = { ino: s.ino, size: s.size };
|
|
180
|
+
}
|
|
181
|
+
catch {
|
|
182
|
+
state.fileStates.delete(path);
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
const prev = state.fileStates.get(path);
|
|
186
|
+
// First sighting: anchor to current size. Existing content predates
|
|
187
|
+
// this poller and is assumed already counted by whatever metric path
|
|
188
|
+
// was active before. We only emit for bytes appended after startup.
|
|
189
|
+
if (!prev) {
|
|
190
|
+
state.fileStates.set(path, {
|
|
191
|
+
offset: info.size,
|
|
192
|
+
inode: info.ino,
|
|
193
|
+
size: info.size,
|
|
194
|
+
});
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
// Rotation or truncation: re-anchor and skip emission for this tick.
|
|
198
|
+
if (prev.inode !== info.ino || info.size < prev.size) {
|
|
199
|
+
state.fileStates.set(path, {
|
|
200
|
+
offset: info.size,
|
|
201
|
+
inode: info.ino,
|
|
202
|
+
size: info.size,
|
|
203
|
+
});
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
if (info.size === prev.offset) {
|
|
207
|
+
state.fileStates.set(path, {
|
|
208
|
+
offset: prev.offset,
|
|
209
|
+
inode: info.ino,
|
|
210
|
+
size: info.size,
|
|
211
|
+
});
|
|
212
|
+
return;
|
|
213
|
+
}
|
|
214
|
+
const chunk = await readBytes(path, prev.offset, info.size);
|
|
215
|
+
const consumed = parseAndEmit(chunk, state);
|
|
216
|
+
state.fileStates.set(path, {
|
|
217
|
+
offset: prev.offset + consumed,
|
|
218
|
+
inode: info.ino,
|
|
219
|
+
size: info.size,
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
function readBytes(path, start, end) {
|
|
223
|
+
return new Promise((resolve, reject) => {
|
|
224
|
+
const parts = [];
|
|
225
|
+
const stream = createReadStream(path, {
|
|
226
|
+
start,
|
|
227
|
+
end: Math.max(start, end - 1),
|
|
228
|
+
encoding: "utf8",
|
|
229
|
+
});
|
|
230
|
+
stream.on("data", (chunk) => {
|
|
231
|
+
parts.push(typeof chunk === "string" ? chunk : chunk.toString("utf8"));
|
|
232
|
+
});
|
|
233
|
+
stream.on("end", () => resolve(parts.join("")));
|
|
234
|
+
stream.on("error", reject);
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
function parseAndEmit(chunk, state) {
|
|
238
|
+
if (chunk.length === 0)
|
|
239
|
+
return 0;
|
|
240
|
+
// Trailing bytes after the last `\n` are a partial line still being
|
|
241
|
+
// flushed by openclaw. Leave them for the next tick.
|
|
242
|
+
const lastNewline = chunk.lastIndexOf("\n");
|
|
243
|
+
if (lastNewline === -1)
|
|
244
|
+
return 0;
|
|
245
|
+
const lines = chunk.slice(0, lastNewline).split("\n");
|
|
246
|
+
for (const line of lines) {
|
|
247
|
+
if (line.length === 0 || line.trim().length === 0)
|
|
248
|
+
continue;
|
|
249
|
+
let parsed;
|
|
250
|
+
try {
|
|
251
|
+
parsed = JSON.parse(line);
|
|
252
|
+
}
|
|
253
|
+
catch {
|
|
254
|
+
continue;
|
|
255
|
+
}
|
|
256
|
+
emitFromEntry(parsed, state);
|
|
257
|
+
}
|
|
258
|
+
return lastNewline + 1;
|
|
259
|
+
}
|
|
260
|
+
function emitFromEntry(entry, state) {
|
|
261
|
+
if (!state.counter || !isRecord(entry))
|
|
262
|
+
return;
|
|
263
|
+
if (readProvider(entry) !== RUNWARE_PROVIDER)
|
|
264
|
+
return;
|
|
265
|
+
const cost = readCostUsd(entry);
|
|
266
|
+
if (cost <= 0)
|
|
267
|
+
return;
|
|
268
|
+
const attrs = {
|
|
269
|
+
"openclaw.provider": RUNWARE_PROVIDER,
|
|
270
|
+
"openclaw.model": readModel(entry) ?? "unknown",
|
|
271
|
+
};
|
|
272
|
+
const channel = readChannel(entry);
|
|
273
|
+
if (channel)
|
|
274
|
+
attrs["openclaw.channel"] = channel;
|
|
275
|
+
try {
|
|
276
|
+
state.counter.add(cost, attrs);
|
|
277
|
+
if (!state.emittedAny) {
|
|
278
|
+
state.emittedAny = true;
|
|
279
|
+
console.log(`[runware-cost-metric] first emit: ${cost.toFixed(6)} USD ${JSON.stringify(attrs)}`);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
catch (err) {
|
|
283
|
+
console.error("[runware-cost-metric] counter.add failed:", err);
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
function isRecord(v) {
|
|
287
|
+
return v !== null && typeof v === "object";
|
|
288
|
+
}
|
|
289
|
+
function readProvider(entry) {
|
|
290
|
+
if (typeof entry.provider === "string")
|
|
291
|
+
return entry.provider;
|
|
292
|
+
const model = entry.model;
|
|
293
|
+
if (typeof model === "string") {
|
|
294
|
+
const slash = model.indexOf("/");
|
|
295
|
+
if (slash > 0)
|
|
296
|
+
return model.slice(0, slash);
|
|
297
|
+
}
|
|
298
|
+
return undefined;
|
|
299
|
+
}
|
|
300
|
+
function readCostUsd(entry) {
|
|
301
|
+
const usage = entry.usage;
|
|
302
|
+
if (isRecord(usage)) {
|
|
303
|
+
const cost = usage.cost;
|
|
304
|
+
if (isRecord(cost) &&
|
|
305
|
+
typeof cost.total === "number" &&
|
|
306
|
+
Number.isFinite(cost.total)) {
|
|
307
|
+
return cost.total;
|
|
308
|
+
}
|
|
309
|
+
if (typeof usage.costUsd === "number" &&
|
|
310
|
+
Number.isFinite(usage.costUsd)) {
|
|
311
|
+
return usage.costUsd;
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
if (typeof entry.costUsd === "number" && Number.isFinite(entry.costUsd)) {
|
|
315
|
+
return entry.costUsd;
|
|
316
|
+
}
|
|
317
|
+
return 0;
|
|
318
|
+
}
|
|
319
|
+
function readModel(entry) {
|
|
320
|
+
if (typeof entry.model === "string")
|
|
321
|
+
return entry.model;
|
|
322
|
+
if (typeof entry.modelId === "string")
|
|
323
|
+
return entry.modelId;
|
|
324
|
+
return undefined;
|
|
325
|
+
}
|
|
326
|
+
function readChannel(entry) {
|
|
327
|
+
if (typeof entry.channel === "string")
|
|
328
|
+
return entry.channel;
|
|
329
|
+
const meta = entry.metadata;
|
|
330
|
+
if (isRecord(meta) && typeof meta.channel === "string")
|
|
331
|
+
return meta.channel;
|
|
332
|
+
return undefined;
|
|
333
|
+
}
|
|
334
|
+
//# 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"}
|
package/dist/models.d.ts
CHANGED
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
* Runware hasn't published those limits fall back to conservative
|
|
10
10
|
* provider defaults so OpenClaw never sees a missing value.
|
|
11
11
|
*/
|
|
12
|
+
export type ModelInput = ["text"] | ["text", "image"];
|
|
12
13
|
export declare const PROVIDER_ID = "runware";
|
|
13
14
|
export declare const PROVIDER_LABEL = "Runware";
|
|
14
15
|
export declare const DEFAULT_BASE_URL = "https://api.runware.ai/v1";
|
|
@@ -31,7 +32,7 @@ export interface ModelEntry {
|
|
|
31
32
|
id: string;
|
|
32
33
|
name: string;
|
|
33
34
|
reasoning: true;
|
|
34
|
-
input:
|
|
35
|
+
input: ModelInput;
|
|
35
36
|
contextWindow: number;
|
|
36
37
|
maxTokens: number;
|
|
37
38
|
cost: ModelCost;
|
|
@@ -51,7 +52,7 @@ export interface ModelCatalogRow {
|
|
|
51
52
|
label: string;
|
|
52
53
|
source: "live";
|
|
53
54
|
reasoning: true;
|
|
54
|
-
input:
|
|
55
|
+
input: ModelInput;
|
|
55
56
|
contextWindow: number;
|
|
56
57
|
maxTokens: number;
|
|
57
58
|
cost: ModelCost;
|
package/dist/models.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"models.d.ts","sourceRoot":"","sources":["../src/models.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAKH,eAAO,MAAM,WAAW,YAAY,CAAC;AACrC,eAAO,MAAM,cAAc,YAAY,CAAC;AACxC,eAAO,MAAM,gBAAgB,8BAA8B,CAAC;AAC5D,eAAO,MAAM,eAAe,oBAAoB,CAAC;AACjD,eAAO,MAAM,gBAAgB,qBAAqB,CAAC;AAGnD,eAAO,MAAM,sBAAsB,SAAU,CAAC;AAC9C,eAAO,MAAM,kBAAkB,QAAS,CAAC;AACzC,QAAA,MAAM,YAAY;;;;CAAwD,CAAC;AAG3E,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,IAAI,CAAC;IAChB,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"models.d.ts","sourceRoot":"","sources":["../src/models.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAKH,MAAM,MAAM,UAAU,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAEtD,eAAO,MAAM,WAAW,YAAY,CAAC;AACrC,eAAO,MAAM,cAAc,YAAY,CAAC;AACxC,eAAO,MAAM,gBAAgB,8BAA8B,CAAC;AAC5D,eAAO,MAAM,eAAe,oBAAoB,CAAC;AACjD,eAAO,MAAM,gBAAgB,qBAAqB,CAAC;AAGnD,eAAO,MAAM,sBAAsB,SAAU,CAAC;AAC9C,eAAO,MAAM,kBAAkB,QAAS,CAAC;AACzC,QAAA,MAAM,YAAY;;;;CAAwD,CAAC;AAG3E,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,IAAI,CAAC;IAChB,KAAK,EAAE,UAAU,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,SAAS,CAAC;IAChB,MAAM,EAAE,OAAO,YAAY,CAAC;CAC7B;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,oBAAoB,CAAC;IAC1B,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,UAAU,EAAE,CAAC;CACtB;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,IAAI,CAAC;IAChB,KAAK,EAAE,UAAU,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,SAAS,CAAC;CACjB;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAQlD;AAMD;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,GAAG,MAAM,CAI/E;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE;IACjC,qBAAqB,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK;QAAE,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACpE,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;CAC1C,GAAG,MAAM,GAAG,SAAS,CAKrB;AA2CD;;;;;GAKG;AACH,wBAAsB,aAAa,CACjC,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,aAAa,CAAC,CASxB;AAED;;;;;GAKG;AACH,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,eAAe,EAAE,CAAC,CAG5B"}
|
package/dist/models.js
CHANGED
|
@@ -72,6 +72,9 @@ export function resolveApiKey(ctx) {
|
|
|
72
72
|
const fromAuth = ctx.resolveProviderApiKey?.(PROVIDER_ID).apiKey;
|
|
73
73
|
return typeof fromAuth === "string" && fromAuth.length > 0 ? fromAuth : undefined;
|
|
74
74
|
}
|
|
75
|
+
function buildModelInput(model) {
|
|
76
|
+
return model.inputModalities?.includes("image") ? ["text", "image"] : ["text"];
|
|
77
|
+
}
|
|
75
78
|
function buildModelCost(model) {
|
|
76
79
|
return {
|
|
77
80
|
input: model.inputCost ?? DEFAULT_COST.input,
|
|
@@ -85,7 +88,7 @@ function buildModelEntry(model) {
|
|
|
85
88
|
id: model.id,
|
|
86
89
|
name: displayName(model),
|
|
87
90
|
reasoning: true,
|
|
88
|
-
input:
|
|
91
|
+
input: buildModelInput(model),
|
|
89
92
|
contextWindow: model.contextLength ?? DEFAULT_CONTEXT_WINDOW,
|
|
90
93
|
maxTokens: model.maxOutputTokens ?? DEFAULT_MAX_TOKENS,
|
|
91
94
|
cost: buildModelCost(model),
|
|
@@ -100,7 +103,7 @@ function buildCatalogRow(model) {
|
|
|
100
103
|
label: displayName(model),
|
|
101
104
|
source: "live",
|
|
102
105
|
reasoning: true,
|
|
103
|
-
input:
|
|
106
|
+
input: buildModelInput(model),
|
|
104
107
|
contextWindow: model.contextLength ?? DEFAULT_CONTEXT_WINDOW,
|
|
105
108
|
maxTokens: model.maxOutputTokens ?? DEFAULT_MAX_TOKENS,
|
|
106
109
|
cost: buildModelCost(model),
|
package/dist/models.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"models.js","sourceRoot":"","sources":["../src/models.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"models.js","sourceRoot":"","sources":["../src/models.ts"],"names":[],"mappings":"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"}
|
|
@@ -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.4",
|
|
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",
|