@blockrun/clawrouter 0.12.229 → 0.12.230
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/cli.js +76 -6
- package/dist/index.js +76 -6
- package/package.json +1 -1
- package/scripts/update.sh +122 -30
package/dist/cli.js
CHANGED
|
@@ -82181,6 +82181,65 @@ function extractGptCalls(content) {
|
|
|
82181
82181
|
}
|
|
82182
82182
|
return { calls: [], matches: [] };
|
|
82183
82183
|
}
|
|
82184
|
+
function deriveRequestTools(tools) {
|
|
82185
|
+
if (!Array.isArray(tools)) return [];
|
|
82186
|
+
const derived = [];
|
|
82187
|
+
for (const raw of tools) {
|
|
82188
|
+
const fn = raw?.function;
|
|
82189
|
+
const name = fn?.name;
|
|
82190
|
+
if (typeof name !== "string" || name.trim() === "") continue;
|
|
82191
|
+
const params = fn?.parameters;
|
|
82192
|
+
const props = isPlainObject(params?.properties) ? Object.keys(params.properties) : [];
|
|
82193
|
+
const required = Array.isArray(params?.required) ? params.required.filter((r2) => typeof r2 === "string") : [];
|
|
82194
|
+
derived.push({ name: name.trim(), propKeys: new Set(props), required });
|
|
82195
|
+
}
|
|
82196
|
+
return derived;
|
|
82197
|
+
}
|
|
82198
|
+
function keyMatchesParam(key2, propKeys) {
|
|
82199
|
+
if (propKeys.has(key2)) return true;
|
|
82200
|
+
if (key2 === "cmd" && propKeys.has("command")) return true;
|
|
82201
|
+
if (key2 === "command" && propKeys.has("cmd")) return true;
|
|
82202
|
+
return false;
|
|
82203
|
+
}
|
|
82204
|
+
function requiredSatisfied(tool, blobKeys) {
|
|
82205
|
+
return tool.required.every(
|
|
82206
|
+
(r2) => blobKeys.has(r2) || r2 === "command" && blobKeys.has("cmd") || r2 === "cmd" && blobKeys.has("command")
|
|
82207
|
+
);
|
|
82208
|
+
}
|
|
82209
|
+
function resolveKimiTool(prose, blob, tools) {
|
|
82210
|
+
const blobKeys = Object.keys(blob);
|
|
82211
|
+
if (prose) {
|
|
82212
|
+
const named = tools.filter(
|
|
82213
|
+
(t) => new RegExp(`(?:^|[^A-Za-z0-9_])${escapeRegExp2(t.name)}(?:[^A-Za-z0-9_]|$)`).test(prose)
|
|
82214
|
+
);
|
|
82215
|
+
if (named.length === 1) return named[0].name;
|
|
82216
|
+
}
|
|
82217
|
+
if (blobKeys.length === 0) return null;
|
|
82218
|
+
const keySet = new Set(blobKeys);
|
|
82219
|
+
const sigMatches = tools.filter(
|
|
82220
|
+
(t) => blobKeys.every((k) => keyMatchesParam(k, t.propKeys)) && requiredSatisfied(t, keySet)
|
|
82221
|
+
);
|
|
82222
|
+
return sigMatches.length === 1 ? sigMatches[0].name : null;
|
|
82223
|
+
}
|
|
82224
|
+
function escapeRegExp2(s3) {
|
|
82225
|
+
return s3.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
82226
|
+
}
|
|
82227
|
+
function extractKimiCalls(content, tools) {
|
|
82228
|
+
if (tools.length === 0) return { calls: [], matches: [] };
|
|
82229
|
+
const trailing = findTrailingJsonObject(content);
|
|
82230
|
+
if (!trailing || !isPlainObject(trailing.parsed)) return { calls: [], matches: [] };
|
|
82231
|
+
if (typeof trailing.parsed.name === "string" && trailing.parsed.name.trim() !== "") {
|
|
82232
|
+
return { calls: [], matches: [] };
|
|
82233
|
+
}
|
|
82234
|
+
const prose = content.slice(0, trailing.start).trim();
|
|
82235
|
+
const name = resolveKimiTool(prose, trailing.parsed, tools);
|
|
82236
|
+
if (!name) return { calls: [], matches: [] };
|
|
82237
|
+
const start = prose === "" ? 0 : trailing.start;
|
|
82238
|
+
return {
|
|
82239
|
+
calls: [makeCall(name, normalizeGptArgs(trailing.parsed))],
|
|
82240
|
+
matches: [{ start, end: content.length }]
|
|
82241
|
+
};
|
|
82242
|
+
}
|
|
82184
82243
|
function stripRanges(content, ranges) {
|
|
82185
82244
|
if (ranges.length === 0) return content;
|
|
82186
82245
|
const sorted = [...ranges].sort((a, b) => a.start - b.start);
|
|
@@ -82195,15 +82254,23 @@ function stripRanges(content, ranges) {
|
|
|
82195
82254
|
cleaned += content.slice(cursor);
|
|
82196
82255
|
return cleaned;
|
|
82197
82256
|
}
|
|
82198
|
-
function extractTextualToolCalls(content) {
|
|
82257
|
+
function extractTextualToolCalls(content, options) {
|
|
82199
82258
|
if (!content) {
|
|
82200
82259
|
return { toolCalls: [], cleanedContent: "" };
|
|
82201
82260
|
}
|
|
82202
82261
|
const openClaw = extractOpenClawCalls(content);
|
|
82203
82262
|
const anthropic = extractAnthropicCalls(content);
|
|
82204
82263
|
const gemini = extractGeminiCalls(content);
|
|
82205
|
-
const
|
|
82206
|
-
const
|
|
82264
|
+
const tagBasedCount = openClaw.calls.length + anthropic.calls.length + gemini.calls.length;
|
|
82265
|
+
const gpt = tagBasedCount === 0 ? extractGptCalls(content) : { calls: [], matches: [] };
|
|
82266
|
+
const kimi = tagBasedCount + gpt.calls.length === 0 ? extractKimiCalls(content, deriveRequestTools(options?.tools)) : { calls: [], matches: [] };
|
|
82267
|
+
const toolCalls = [
|
|
82268
|
+
...openClaw.calls,
|
|
82269
|
+
...anthropic.calls,
|
|
82270
|
+
...gemini.calls,
|
|
82271
|
+
...gpt.calls,
|
|
82272
|
+
...kimi.calls
|
|
82273
|
+
];
|
|
82207
82274
|
if (toolCalls.length === 0) {
|
|
82208
82275
|
return { toolCalls: [], cleanedContent: content };
|
|
82209
82276
|
}
|
|
@@ -82211,7 +82278,8 @@ function extractTextualToolCalls(content) {
|
|
|
82211
82278
|
...openClaw.matches,
|
|
82212
82279
|
...anthropic.matches,
|
|
82213
82280
|
...gemini.matches,
|
|
82214
|
-
...gpt.matches
|
|
82281
|
+
...gpt.matches,
|
|
82282
|
+
...kimi.matches
|
|
82215
82283
|
]);
|
|
82216
82284
|
return { toolCalls, cleanedContent };
|
|
82217
82285
|
}
|
|
@@ -85986,6 +86054,7 @@ async function proxyRequest(req, res, apiBase, payFetch, options, routerOpts, de
|
|
|
85986
86054
|
const debugMode = debugHeadersEnabledFromEnv() && req.headers["x-clawrouter-debug"] !== "false";
|
|
85987
86055
|
let routingDecision;
|
|
85988
86056
|
let hasTools = false;
|
|
86057
|
+
let requestTools;
|
|
85989
86058
|
let hasVision = false;
|
|
85990
86059
|
let isStreaming = false;
|
|
85991
86060
|
let modelId = "";
|
|
@@ -86023,6 +86092,7 @@ async function proxyRequest(req, res, apiBase, payFetch, options, routerOpts, de
|
|
|
86023
86092
|
requestSummaryForStore = summarizeRequest(promptText);
|
|
86024
86093
|
}
|
|
86025
86094
|
hasTools = Array.isArray(parsed.tools) && parsed.tools.length > 0;
|
|
86095
|
+
requestTools = parsed.tools;
|
|
86026
86096
|
const rawLastContent = lastUserMsg?.content;
|
|
86027
86097
|
const lastContent = typeof rawLastContent === "string" ? rawLastContent : Array.isArray(rawLastContent) ? rawLastContent.filter((b) => b.type === "text").map((b) => b.text ?? "").join(" ") : "";
|
|
86028
86098
|
if (sessionId && parsedMessages.length > 0) {
|
|
@@ -87566,7 +87636,7 @@ data: [DONE]
|
|
|
87566
87636
|
let toolCalls = choice.message?.tool_calls ?? choice.delta?.tool_calls;
|
|
87567
87637
|
const rawContent = choice.message?.content ?? choice.delta?.content ?? "";
|
|
87568
87638
|
if (!endsWithToolCalls && (!toolCalls || toolCalls.length === 0) && rawContent) {
|
|
87569
|
-
const extracted = extractTextualToolCalls(rawContent);
|
|
87639
|
+
const extracted = extractTextualToolCalls(rawContent, { tools: requestTools });
|
|
87570
87640
|
if (extracted.toolCalls.length > 0) {
|
|
87571
87641
|
toolCalls = extracted.toolCalls;
|
|
87572
87642
|
}
|
|
@@ -87779,7 +87849,7 @@ data: [DONE]
|
|
|
87779
87849
|
}
|
|
87780
87850
|
continue;
|
|
87781
87851
|
}
|
|
87782
|
-
const extracted = extractTextualToolCalls(message.content);
|
|
87852
|
+
const extracted = extractTextualToolCalls(message.content, { tools: requestTools });
|
|
87783
87853
|
if (extracted.toolCalls.length > 0) {
|
|
87784
87854
|
message.tool_calls = extracted.toolCalls;
|
|
87785
87855
|
message.content = "";
|
package/dist/index.js
CHANGED
|
@@ -82001,6 +82001,65 @@ function extractGptCalls(content) {
|
|
|
82001
82001
|
}
|
|
82002
82002
|
return { calls: [], matches: [] };
|
|
82003
82003
|
}
|
|
82004
|
+
function deriveRequestTools(tools) {
|
|
82005
|
+
if (!Array.isArray(tools)) return [];
|
|
82006
|
+
const derived = [];
|
|
82007
|
+
for (const raw of tools) {
|
|
82008
|
+
const fn = raw?.function;
|
|
82009
|
+
const name = fn?.name;
|
|
82010
|
+
if (typeof name !== "string" || name.trim() === "") continue;
|
|
82011
|
+
const params = fn?.parameters;
|
|
82012
|
+
const props = isPlainObject(params?.properties) ? Object.keys(params.properties) : [];
|
|
82013
|
+
const required = Array.isArray(params?.required) ? params.required.filter((r2) => typeof r2 === "string") : [];
|
|
82014
|
+
derived.push({ name: name.trim(), propKeys: new Set(props), required });
|
|
82015
|
+
}
|
|
82016
|
+
return derived;
|
|
82017
|
+
}
|
|
82018
|
+
function keyMatchesParam(key2, propKeys) {
|
|
82019
|
+
if (propKeys.has(key2)) return true;
|
|
82020
|
+
if (key2 === "cmd" && propKeys.has("command")) return true;
|
|
82021
|
+
if (key2 === "command" && propKeys.has("cmd")) return true;
|
|
82022
|
+
return false;
|
|
82023
|
+
}
|
|
82024
|
+
function requiredSatisfied(tool, blobKeys) {
|
|
82025
|
+
return tool.required.every(
|
|
82026
|
+
(r2) => blobKeys.has(r2) || r2 === "command" && blobKeys.has("cmd") || r2 === "cmd" && blobKeys.has("command")
|
|
82027
|
+
);
|
|
82028
|
+
}
|
|
82029
|
+
function resolveKimiTool(prose, blob, tools) {
|
|
82030
|
+
const blobKeys = Object.keys(blob);
|
|
82031
|
+
if (prose) {
|
|
82032
|
+
const named = tools.filter(
|
|
82033
|
+
(t) => new RegExp(`(?:^|[^A-Za-z0-9_])${escapeRegExp2(t.name)}(?:[^A-Za-z0-9_]|$)`).test(prose)
|
|
82034
|
+
);
|
|
82035
|
+
if (named.length === 1) return named[0].name;
|
|
82036
|
+
}
|
|
82037
|
+
if (blobKeys.length === 0) return null;
|
|
82038
|
+
const keySet = new Set(blobKeys);
|
|
82039
|
+
const sigMatches = tools.filter(
|
|
82040
|
+
(t) => blobKeys.every((k) => keyMatchesParam(k, t.propKeys)) && requiredSatisfied(t, keySet)
|
|
82041
|
+
);
|
|
82042
|
+
return sigMatches.length === 1 ? sigMatches[0].name : null;
|
|
82043
|
+
}
|
|
82044
|
+
function escapeRegExp2(s3) {
|
|
82045
|
+
return s3.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
82046
|
+
}
|
|
82047
|
+
function extractKimiCalls(content, tools) {
|
|
82048
|
+
if (tools.length === 0) return { calls: [], matches: [] };
|
|
82049
|
+
const trailing = findTrailingJsonObject(content);
|
|
82050
|
+
if (!trailing || !isPlainObject(trailing.parsed)) return { calls: [], matches: [] };
|
|
82051
|
+
if (typeof trailing.parsed.name === "string" && trailing.parsed.name.trim() !== "") {
|
|
82052
|
+
return { calls: [], matches: [] };
|
|
82053
|
+
}
|
|
82054
|
+
const prose = content.slice(0, trailing.start).trim();
|
|
82055
|
+
const name = resolveKimiTool(prose, trailing.parsed, tools);
|
|
82056
|
+
if (!name) return { calls: [], matches: [] };
|
|
82057
|
+
const start = prose === "" ? 0 : trailing.start;
|
|
82058
|
+
return {
|
|
82059
|
+
calls: [makeCall(name, normalizeGptArgs(trailing.parsed))],
|
|
82060
|
+
matches: [{ start, end: content.length }]
|
|
82061
|
+
};
|
|
82062
|
+
}
|
|
82004
82063
|
function stripRanges(content, ranges) {
|
|
82005
82064
|
if (ranges.length === 0) return content;
|
|
82006
82065
|
const sorted = [...ranges].sort((a, b) => a.start - b.start);
|
|
@@ -82015,15 +82074,23 @@ function stripRanges(content, ranges) {
|
|
|
82015
82074
|
cleaned += content.slice(cursor);
|
|
82016
82075
|
return cleaned;
|
|
82017
82076
|
}
|
|
82018
|
-
function extractTextualToolCalls(content) {
|
|
82077
|
+
function extractTextualToolCalls(content, options) {
|
|
82019
82078
|
if (!content) {
|
|
82020
82079
|
return { toolCalls: [], cleanedContent: "" };
|
|
82021
82080
|
}
|
|
82022
82081
|
const openClaw = extractOpenClawCalls(content);
|
|
82023
82082
|
const anthropic = extractAnthropicCalls(content);
|
|
82024
82083
|
const gemini = extractGeminiCalls(content);
|
|
82025
|
-
const
|
|
82026
|
-
const
|
|
82084
|
+
const tagBasedCount = openClaw.calls.length + anthropic.calls.length + gemini.calls.length;
|
|
82085
|
+
const gpt = tagBasedCount === 0 ? extractGptCalls(content) : { calls: [], matches: [] };
|
|
82086
|
+
const kimi = tagBasedCount + gpt.calls.length === 0 ? extractKimiCalls(content, deriveRequestTools(options?.tools)) : { calls: [], matches: [] };
|
|
82087
|
+
const toolCalls = [
|
|
82088
|
+
...openClaw.calls,
|
|
82089
|
+
...anthropic.calls,
|
|
82090
|
+
...gemini.calls,
|
|
82091
|
+
...gpt.calls,
|
|
82092
|
+
...kimi.calls
|
|
82093
|
+
];
|
|
82027
82094
|
if (toolCalls.length === 0) {
|
|
82028
82095
|
return { toolCalls: [], cleanedContent: content };
|
|
82029
82096
|
}
|
|
@@ -82031,7 +82098,8 @@ function extractTextualToolCalls(content) {
|
|
|
82031
82098
|
...openClaw.matches,
|
|
82032
82099
|
...anthropic.matches,
|
|
82033
82100
|
...gemini.matches,
|
|
82034
|
-
...gpt.matches
|
|
82101
|
+
...gpt.matches,
|
|
82102
|
+
...kimi.matches
|
|
82035
82103
|
]);
|
|
82036
82104
|
return { toolCalls, cleanedContent };
|
|
82037
82105
|
}
|
|
@@ -85806,6 +85874,7 @@ async function proxyRequest(req, res, apiBase, payFetch, options, routerOpts, de
|
|
|
85806
85874
|
const debugMode = debugHeadersEnabledFromEnv() && req.headers["x-clawrouter-debug"] !== "false";
|
|
85807
85875
|
let routingDecision;
|
|
85808
85876
|
let hasTools = false;
|
|
85877
|
+
let requestTools;
|
|
85809
85878
|
let hasVision = false;
|
|
85810
85879
|
let isStreaming = false;
|
|
85811
85880
|
let modelId = "";
|
|
@@ -85843,6 +85912,7 @@ async function proxyRequest(req, res, apiBase, payFetch, options, routerOpts, de
|
|
|
85843
85912
|
requestSummaryForStore = summarizeRequest(promptText);
|
|
85844
85913
|
}
|
|
85845
85914
|
hasTools = Array.isArray(parsed.tools) && parsed.tools.length > 0;
|
|
85915
|
+
requestTools = parsed.tools;
|
|
85846
85916
|
const rawLastContent = lastUserMsg?.content;
|
|
85847
85917
|
const lastContent = typeof rawLastContent === "string" ? rawLastContent : Array.isArray(rawLastContent) ? rawLastContent.filter((b) => b.type === "text").map((b) => b.text ?? "").join(" ") : "";
|
|
85848
85918
|
if (sessionId && parsedMessages.length > 0) {
|
|
@@ -87386,7 +87456,7 @@ data: [DONE]
|
|
|
87386
87456
|
let toolCalls = choice.message?.tool_calls ?? choice.delta?.tool_calls;
|
|
87387
87457
|
const rawContent = choice.message?.content ?? choice.delta?.content ?? "";
|
|
87388
87458
|
if (!endsWithToolCalls && (!toolCalls || toolCalls.length === 0) && rawContent) {
|
|
87389
|
-
const extracted = extractTextualToolCalls(rawContent);
|
|
87459
|
+
const extracted = extractTextualToolCalls(rawContent, { tools: requestTools });
|
|
87390
87460
|
if (extracted.toolCalls.length > 0) {
|
|
87391
87461
|
toolCalls = extracted.toolCalls;
|
|
87392
87462
|
}
|
|
@@ -87599,7 +87669,7 @@ data: [DONE]
|
|
|
87599
87669
|
}
|
|
87600
87670
|
continue;
|
|
87601
87671
|
}
|
|
87602
|
-
const extracted = extractTextualToolCalls(message.content);
|
|
87672
|
+
const extracted = extractTextualToolCalls(message.content, { tools: requestTools });
|
|
87603
87673
|
if (extracted.toolCalls.length > 0) {
|
|
87604
87674
|
message.tool_calls = extracted.toolCalls;
|
|
87605
87675
|
message.content = "";
|
package/package.json
CHANGED
package/scripts/update.sh
CHANGED
|
@@ -16,6 +16,96 @@ WALLET_FILE="$HOME/.openclaw/blockrun/wallet.key"
|
|
|
16
16
|
WALLET_BACKUP=""
|
|
17
17
|
PLUGIN_BACKUP=""
|
|
18
18
|
CONFIG_BACKUP=""
|
|
19
|
+
ACTIVE_PACKAGE_DIR=""
|
|
20
|
+
|
|
21
|
+
NPM_PREFIX="$(npm config get prefix 2>/dev/null || echo "")"
|
|
22
|
+
if [ -n "$NPM_PREFIX" ] && [ -d "$NPM_PREFIX/bin" ]; then
|
|
23
|
+
PATH="$NPM_PREFIX/bin:$PATH"
|
|
24
|
+
export PATH
|
|
25
|
+
fi
|
|
26
|
+
|
|
27
|
+
find_clawrouter_package_dir() {
|
|
28
|
+
node <<'NODE'
|
|
29
|
+
const fs = require('fs');
|
|
30
|
+
const os = require('os');
|
|
31
|
+
const path = require('path');
|
|
32
|
+
|
|
33
|
+
const home = os.homedir();
|
|
34
|
+
const candidates = [
|
|
35
|
+
{ packagePath: path.join(home, '.openclaw', 'extensions', 'clawrouter', 'package.json'), priority: 0 },
|
|
36
|
+
{ packagePath: path.join(home, '.openclaw', 'npm', 'node_modules', '@blockrun', 'clawrouter', 'package.json'), priority: 2 },
|
|
37
|
+
];
|
|
38
|
+
|
|
39
|
+
const projectsDir = path.join(home, '.openclaw', 'npm', 'projects');
|
|
40
|
+
try {
|
|
41
|
+
for (const name of fs.readdirSync(projectsDir)) {
|
|
42
|
+
candidates.push({
|
|
43
|
+
packagePath: path.join(projectsDir, name, 'node_modules', '@blockrun', 'clawrouter', 'package.json'),
|
|
44
|
+
priority: 1,
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
} catch {}
|
|
48
|
+
|
|
49
|
+
function versionParts(version) {
|
|
50
|
+
return String(version || '').split(/[.-]/).slice(0, 3).map((part) => Number.parseInt(part, 10) || 0);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function compareVersions(a, b) {
|
|
54
|
+
const left = versionParts(a);
|
|
55
|
+
const right = versionParts(b);
|
|
56
|
+
for (let i = 0; i < 3; i++) {
|
|
57
|
+
if (left[i] !== right[i]) return left[i] - right[i];
|
|
58
|
+
}
|
|
59
|
+
return 0;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
let best = null;
|
|
63
|
+
for (const candidate of candidates) {
|
|
64
|
+
try {
|
|
65
|
+
const stat = fs.statSync(candidate.packagePath);
|
|
66
|
+
const pkg = JSON.parse(fs.readFileSync(candidate.packagePath, 'utf8'));
|
|
67
|
+
if (pkg?.name !== '@blockrun/clawrouter') continue;
|
|
68
|
+
const versionOrder = best ? compareVersions(pkg.version, best.pkg.version) : 1;
|
|
69
|
+
if (
|
|
70
|
+
!best ||
|
|
71
|
+
versionOrder > 0 ||
|
|
72
|
+
(versionOrder === 0 &&
|
|
73
|
+
(candidate.priority < best.priority ||
|
|
74
|
+
(candidate.priority === best.priority && stat.mtimeMs > best.mtimeMs)))
|
|
75
|
+
) {
|
|
76
|
+
best = { ...candidate, pkg, mtimeMs: stat.mtimeMs };
|
|
77
|
+
}
|
|
78
|
+
} catch {}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (best) console.log(path.dirname(best.packagePath));
|
|
82
|
+
NODE
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
sync_cli_shim() {
|
|
86
|
+
local package_dir="$1"
|
|
87
|
+
if [ -z "$package_dir" ] || [ ! -f "$package_dir/dist/cli.js" ]; then
|
|
88
|
+
echo " ⚠ Could not update CLI shim: ClawRouter CLI not found"
|
|
89
|
+
return 1
|
|
90
|
+
fi
|
|
91
|
+
|
|
92
|
+
local prefix
|
|
93
|
+
prefix=$(npm config get prefix 2>/dev/null || echo "")
|
|
94
|
+
if [ -z "$prefix" ]; then
|
|
95
|
+
echo " ⚠ Could not update CLI shim: npm prefix unavailable"
|
|
96
|
+
return 1
|
|
97
|
+
fi
|
|
98
|
+
|
|
99
|
+
local bin_dir="$prefix/bin"
|
|
100
|
+
mkdir -p "$bin_dir"
|
|
101
|
+
rm -f "$bin_dir/clawrouter"
|
|
102
|
+
cat >"$bin_dir/clawrouter" <<EOF
|
|
103
|
+
#!/bin/sh
|
|
104
|
+
exec node "$package_dir/dist/cli.js" "\$@"
|
|
105
|
+
EOF
|
|
106
|
+
chmod +x "$bin_dir/clawrouter"
|
|
107
|
+
echo " ✓ CLI shim updated: $bin_dir/clawrouter → $package_dir/dist/cli.js"
|
|
108
|
+
}
|
|
19
109
|
|
|
20
110
|
cleanup_backups() {
|
|
21
111
|
if [ -n "$PLUGIN_BACKUP" ] && [ -d "$PLUGIN_BACKUP" ]; then
|
|
@@ -93,6 +183,7 @@ echo ""
|
|
|
93
183
|
|
|
94
184
|
# Pre-flight: fail fast if config is corrupt
|
|
95
185
|
validate_config
|
|
186
|
+
ACTIVE_PACKAGE_DIR=$(find_clawrouter_package_dir)
|
|
96
187
|
|
|
97
188
|
echo "→ Checking wallet..."
|
|
98
189
|
|
|
@@ -105,7 +196,7 @@ if [ -f "$WALLET_FILE" ]; then
|
|
|
105
196
|
# Derive wallet address via node (viem is available post-install)
|
|
106
197
|
WALLET_ADDRESS=$(node -e "
|
|
107
198
|
try {
|
|
108
|
-
const { privateKeyToAccount } = require('
|
|
199
|
+
const { privateKeyToAccount } = require(require.resolve('viem/accounts', { paths: ['$ACTIVE_PACKAGE_DIR'] }));
|
|
109
200
|
const acct = privateKeyToAccount('$WALLET_KEY');
|
|
110
201
|
console.log(acct.address);
|
|
111
202
|
} catch {
|
|
@@ -551,41 +642,42 @@ force_install_from_npm() {
|
|
|
551
642
|
return 1
|
|
552
643
|
}
|
|
553
644
|
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
645
|
+
LATEST_VER=$(npm view @blockrun/clawrouter@latest version 2>/dev/null || echo "")
|
|
646
|
+
if [ -z "$LATEST_VER" ]; then
|
|
647
|
+
echo " ✗ Could not resolve latest ClawRouter version from npm"
|
|
648
|
+
exit 1
|
|
649
|
+
fi
|
|
650
|
+
|
|
651
|
+
ACTIVE_PACKAGE_DIR=$(find_clawrouter_package_dir)
|
|
652
|
+
INSTALLED_VER=""
|
|
653
|
+
if [ -n "$ACTIVE_PACKAGE_DIR" ] && [ -f "$ACTIVE_PACKAGE_DIR/package.json" ]; then
|
|
654
|
+
INSTALLED_VER=$(node -e "try{const p=require('$ACTIVE_PACKAGE_DIR/package.json');console.log(p.version);}catch{console.log('');}" 2>/dev/null || echo "")
|
|
655
|
+
fi
|
|
656
|
+
|
|
657
|
+
if [ "$OPENCLAW_INSTALL_RECOVERABLE" = "1" ] || [ -z "$INSTALLED_VER" ] || [ "$INSTALLED_VER" != "$LATEST_VER" ]; then
|
|
658
|
+
if [ -n "$INSTALLED_VER" ] && [ "$INSTALLED_VER" != "$LATEST_VER" ]; then
|
|
659
|
+
echo " ⚠️ OpenClaw installed v${INSTALLED_VER} but latest is v${LATEST_VER}"
|
|
559
660
|
fi
|
|
560
661
|
force_install_from_npm "$LATEST_VER"
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
exit 1
|
|
564
|
-
fi
|
|
565
|
-
INSTALLED_VER=$(node -e "try{const p=require('$PLUGIN_DIR/package.json');console.log(p.version);}catch{console.log('');}" 2>/dev/null || echo "")
|
|
566
|
-
if [ -z "$INSTALLED_VER" ]; then
|
|
567
|
-
echo " ✗ Could not verify ClawRouter version after npm fallback"
|
|
568
|
-
exit 1
|
|
569
|
-
fi
|
|
570
|
-
echo " ✓ ClawRouter v${INSTALLED_VER} installed"
|
|
571
|
-
trap - EXIT INT TERM
|
|
572
|
-
elif [ -d "$PLUGIN_DIR" ] && [ -f "$PLUGIN_DIR/package.json" ]; then
|
|
573
|
-
INSTALLED_VER=$(node -e "try{const p=require('$PLUGIN_DIR/package.json');console.log(p.version);}catch{console.log('');}" 2>/dev/null || echo "")
|
|
574
|
-
LATEST_VER=$(npm view @blockrun/clawrouter@latest version 2>/dev/null || echo "")
|
|
575
|
-
if [ -n "$LATEST_VER" ] && [ -n "$INSTALLED_VER" ] && [ "$INSTALLED_VER" != "$LATEST_VER" ]; then
|
|
576
|
-
echo " ⚠️ openclaw installed v${INSTALLED_VER} (cached) but latest is v${LATEST_VER}"
|
|
577
|
-
force_install_from_npm "$LATEST_VER" || true
|
|
578
|
-
fi
|
|
579
|
-
INSTALLED_VER=$(node -e "try{const p=require('$PLUGIN_DIR/package.json');console.log(p.version);}catch{console.log('?');}" 2>/dev/null || echo "?")
|
|
580
|
-
echo " ✓ ClawRouter v${INSTALLED_VER} installed"
|
|
662
|
+
ACTIVE_PACKAGE_DIR=$(find_clawrouter_package_dir)
|
|
663
|
+
INSTALLED_VER=$(node -e "try{const p=require('$ACTIVE_PACKAGE_DIR/package.json');console.log(p.version);}catch{console.log('');}" 2>/dev/null || echo "")
|
|
581
664
|
fi
|
|
582
665
|
|
|
666
|
+
if [ -z "$ACTIVE_PACKAGE_DIR" ] || [ -z "$INSTALLED_VER" ]; then
|
|
667
|
+
echo " ✗ Could not verify ClawRouter install"
|
|
668
|
+
exit 1
|
|
669
|
+
fi
|
|
670
|
+
|
|
671
|
+
echo " ✓ ClawRouter v${INSTALLED_VER} installed at $ACTIVE_PACKAGE_DIR"
|
|
672
|
+
sync_cli_shim "$ACTIVE_PACKAGE_DIR"
|
|
673
|
+
trap - EXIT INT TERM
|
|
674
|
+
|
|
583
675
|
# ── Step 4c: Ensure all dependencies are installed ────────────
|
|
584
676
|
# openclaw's plugin installer may skip native/optional deps like @solana/kit.
|
|
585
677
|
# Run npm install in the plugin directory to fill any gaps.
|
|
586
|
-
if [ -
|
|
678
|
+
if [ -n "$ACTIVE_PACKAGE_DIR" ] && [ -f "$ACTIVE_PACKAGE_DIR/package.json" ]; then
|
|
587
679
|
echo "→ Installing dependencies (Solana, x402, etc.)..."
|
|
588
|
-
run_dependency_install "$
|
|
680
|
+
run_dependency_install "$ACTIVE_PACKAGE_DIR"
|
|
589
681
|
fi
|
|
590
682
|
|
|
591
683
|
# ── Step 5: Verify wallet survived ─────────────────────────────
|
|
@@ -724,7 +816,7 @@ const os = require('os');
|
|
|
724
816
|
const fs = require('fs');
|
|
725
817
|
const path = require('path');
|
|
726
818
|
const configPath = path.join(os.homedir(), '.openclaw', 'openclaw.json');
|
|
727
|
-
const topModelsPath = '$
|
|
819
|
+
const topModelsPath = path.join('$ACTIVE_PACKAGE_DIR', 'src', 'top-models.json');
|
|
728
820
|
|
|
729
821
|
if (!fs.existsSync(configPath)) {
|
|
730
822
|
console.log(' No config file found, skipping');
|
|
@@ -1025,7 +1117,7 @@ if [ -f "$WALLET_FILE" ]; then
|
|
|
1025
1117
|
FINAL_KEY=$(cat "$WALLET_FILE" | tr -d '[:space:]')
|
|
1026
1118
|
FINAL_ADDRESS=$(node -e "
|
|
1027
1119
|
try {
|
|
1028
|
-
const { privateKeyToAccount } = require('
|
|
1120
|
+
const { privateKeyToAccount } = require(require.resolve('viem/accounts', { paths: ['$ACTIVE_PACKAGE_DIR'] }));
|
|
1029
1121
|
console.log(privateKeyToAccount('$FINAL_KEY').address);
|
|
1030
1122
|
} catch { console.log('(run /wallet in OpenClaw to see your address)'); }
|
|
1031
1123
|
" 2>/dev/null || echo "(run /wallet in OpenClaw to see your address)")
|