solana-traderclaw 1.0.45 → 1.0.47

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.
@@ -157,7 +157,12 @@ function normalizeTraderAllowlist(config, pluginId) {
157
157
 
158
158
  function stripAnsi(text) {
159
159
  if (typeof text !== "string") return text;
160
- return text.replace(/\x1b\[[0-9;]*m/g, "");
160
+ // Cover all ANSI/VT escape sequences: CSI, OSC, simple escapes, and lone ESC chars.
161
+ return text
162
+ .replace(/\x1b\[[0-9;]*[a-zA-Z]/g, "") // CSI sequences (colours, cursor, etc.)
163
+ .replace(/\x1b\][^\x07\x1b]*(?:\x07|\x1b\\)/g, "") // OSC sequences
164
+ .replace(/\x1b[^[\]]/g, "") // other 2-char escape sequences
165
+ .replace(/\x1b/g, ""); // bare ESC survivors
161
166
  }
162
167
 
163
168
  /**
@@ -201,7 +206,7 @@ function commandExists(cmd) {
201
206
 
202
207
  function getCommandOutput(cmd) {
203
208
  try {
204
- return execSync(cmd, { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"], shell: true }).trim();
209
+ return execSync(cmd, { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"], shell: true, maxBuffer: 50 * 1024 * 1024 }).trim();
205
210
  } catch {
206
211
  return null;
207
212
  }
@@ -1184,7 +1189,7 @@ function listProviderModels(provider) {
1184
1189
  const raw = getCommandOutput(cmd);
1185
1190
  if (!raw) return [];
1186
1191
  try {
1187
- const parsed = JSON.parse(raw);
1192
+ const parsed = JSON.parse(stripAnsi(raw));
1188
1193
  const models = Array.isArray(parsed?.models) ? parsed.models : [];
1189
1194
  return models
1190
1195
  .map((entry) => (entry && typeof entry.key === "string" ? entry.key : ""))
@@ -1195,11 +1200,21 @@ function listProviderModels(provider) {
1195
1200
  }
1196
1201
 
1197
1202
  function fallbackModelForProvider(provider) {
1198
- // When `openclaw models list` fails, use current API ids (verify vs provider docs periodically).
1199
1203
  if (provider === "anthropic") return "anthropic/claude-sonnet-4-6";
1200
1204
  if (provider === "openai") return "openai/gpt-5.4";
1201
1205
  if (provider === "openai-codex") return "openai-codex/gpt-5.4";
1202
1206
  if (provider === "google" || provider === "google-vertex") return "google/gemini-2.5-flash";
1207
+ if (provider === "xai") return "xai/grok-4";
1208
+ if (provider === "deepseek") return "deepseek/deepseek-chat";
1209
+ if (provider === "together") return "together/moonshotai/Kimi-K2.5";
1210
+ if (provider === "groq") return "groq/llama-4-scout-17b-16e-instruct";
1211
+ if (provider === "mistral") return "mistral/mistral-large-latest";
1212
+ if (provider === "perplexity") return "perplexity/sonar-pro";
1213
+ if (provider === "nvidia") return "nvidia/llama-3.3-70b-instruct";
1214
+ if (provider === "minimax") return "minimax/MiniMax-M2.7";
1215
+ if (provider === "moonshot") return "moonshot/kimi-k2";
1216
+ if (provider === "cerebras") return "cerebras/llama-4-scout-17b-16e-instruct";
1217
+ if (provider === "qwen") return "qwen/qwen3-235b-a22b";
1203
1218
  return `${provider}/default`;
1204
1219
  }
1205
1220
 
@@ -1210,6 +1225,15 @@ function providerEnvKey(provider) {
1210
1225
  if (provider === "groq") return "GROQ_API_KEY";
1211
1226
  if (provider === "mistral") return "MISTRAL_API_KEY";
1212
1227
  if (provider === "google" || provider === "google-vertex") return "GEMINI_API_KEY";
1228
+ if (provider === "xai") return "XAI_API_KEY";
1229
+ if (provider === "deepseek") return "DEEPSEEK_API_KEY";
1230
+ if (provider === "together") return "TOGETHER_API_KEY";
1231
+ if (provider === "perplexity") return "PERPLEXITY_API_KEY";
1232
+ if (provider === "nvidia") return "NVIDIA_API_KEY";
1233
+ if (provider === "minimax") return "MINIMAX_API_KEY";
1234
+ if (provider === "moonshot") return "MOONSHOT_API_KEY";
1235
+ if (provider === "cerebras") return "CEREBRAS_API_KEY";
1236
+ if (provider === "qwen") return "DASHSCOPE_API_KEY";
1213
1237
  return "";
1214
1238
  }
1215
1239
 
@@ -2,13 +2,32 @@
2
2
  * Ranks OpenClaw model keys so defaults pick current, working IDs — not alphabetically-first
3
3
  * or legacy IDs that "win" only because of a large YYYYMMDD suffix in the name.
4
4
  *
5
- * References (verify periodically): Anthropic models overview, OpenAI models docs.
5
+ * References (verify periodically): Anthropic models overview, OpenAI models docs, xAI docs.
6
+ * Last verified: 2026-03-29.
6
7
  */
7
8
 
8
- /** IDs that often appear in catalogs but fail or misbehave for chat/agent use */
9
+ /** IDs that appear in catalogs but are retired, deprecated, or misbehave for chat/agent use */
9
10
  export const KNOWN_PROBLEMATIC_MODEL_IDS = new Set([
10
11
  "anthropic/claude-3-5-haiku-20241022",
11
12
  "anthropic/claude-3-haiku-20240307",
13
+ "anthropic/claude-3-opus-20240229",
14
+ "anthropic/claude-3-sonnet-20240229",
15
+ "anthropic/claude-3-5-sonnet-20240620",
16
+ "openai/gpt-4o",
17
+ "openai/gpt-4o-mini",
18
+ "openai/gpt-4-turbo",
19
+ "openai/gpt-4",
20
+ "openai/gpt-3.5-turbo",
21
+ "openai/gpt-5",
22
+ "openai/gpt-5.1",
23
+ "openai/gpt-5.1-codex",
24
+ "openai/gpt-5.1-codex-max",
25
+ "openai/gpt-5.1-codex-mini",
26
+ "openai/gpt-5.1-instant",
27
+ "openai-codex/gpt-5.1",
28
+ "openai-codex/gpt-5.1-codex",
29
+ "openai-codex/gpt-5.1-codex-max",
30
+ "openai-codex/gpt-5.1-codex-mini",
12
31
  ]);
13
32
 
14
33
  const VARIANT_WEIGHT = { sonnet: 80_000, opus: 60_000, haiku: 40_000 };
@@ -56,25 +75,35 @@ function anthropicPreferenceScore(modelId) {
56
75
  if (!meta) {
57
76
  return 1_000_000 + tieBreakerSnapshot(local);
58
77
  }
59
- // Generation must dominate: a dated Haiku 4.5 snapshot must not beat Sonnet 4.6 (see Anthropic model lineup).
60
78
  const generation = meta.major * 10_000 + meta.minor;
61
79
  const v = VARIANT_WEIGHT[meta.variant] || 0;
62
80
  return generation * 1_000_000_000_000 + v + meta.snapshot;
63
81
  }
64
82
 
65
83
  function openaiFamilyScore(local) {
66
- // Prefer GPT-5.x over 4.x over 3.5; higher minor (5.4 vs 5.2) wins; bare gpt-5 below explicit minors.
67
84
  const g5 = local.match(/^gpt-5(?:\.(\d+))?/);
68
85
  if (g5) {
69
86
  const sub = g5[1] ? Number.parseInt(g5[1], 10) : 0;
70
- return 500 * 1_000_000_000 + sub * 1_000_000;
87
+ let s = 500 * 1_000_000_000 + sub * 1_000_000;
88
+ if (local.includes("pro") || local.includes("thinking")) s += 400_000;
89
+ else if (local.includes("nano")) s -= 200_000;
90
+ else if (local.includes("mini")) s -= 100_000;
91
+ else if (local.includes("instant")) s -= 150_000;
92
+ return s;
71
93
  }
72
- if (local.startsWith("gpt-4o-mini")) return 480 * 1_000_000_000;
73
- if (local.startsWith("gpt-4o")) return 485 * 1_000_000_000;
74
- if (local.includes("gpt-4-turbo")) return 470 * 1_000_000_000;
75
- if (local.startsWith("gpt-4")) return 460 * 1_000_000_000;
76
- if (local.includes("gpt-3.5")) return 350 * 1_000_000_000;
77
- if (local.includes("o3") || local.includes("o1")) return 420 * 1_000_000_000;
94
+ const oSeries = local.match(/^o(\d+)/);
95
+ if (oSeries) {
96
+ const gen = Number.parseInt(oSeries[1], 10);
97
+ let score = 490 * 1_000_000_000 + gen * 1_000_000;
98
+ if (local.includes("mini")) score -= 500_000;
99
+ if (local.includes("pro")) score += 200_000;
100
+ return score;
101
+ }
102
+ if (local.startsWith("gpt-4o-mini")) return 380 * 1_000_000_000;
103
+ if (local.startsWith("gpt-4o")) return 385 * 1_000_000_000;
104
+ if (local.includes("gpt-4-turbo")) return 370 * 1_000_000_000;
105
+ if (local.startsWith("gpt-4")) return 360 * 1_000_000_000;
106
+ if (local.includes("gpt-3.5")) return 250 * 1_000_000_000;
78
107
  return 100 * 1_000_000_000;
79
108
  }
80
109
 
@@ -83,16 +112,74 @@ function openaiPreferenceScore(modelId) {
83
112
  const local = raw.includes("/") ? raw.split("/").slice(1).join("/") : raw;
84
113
  let score = openaiFamilyScore(local);
85
114
  score += tieBreakerSnapshot(local);
86
- // Small bump for non-preview stable names
87
115
  if (local.includes("preview")) score -= 50_000_000;
88
116
  return score;
89
117
  }
90
118
 
119
+ function xaiPreferenceScore(modelId) {
120
+ const local = stripPrefix("xai", modelId);
121
+ const grokMatch = local.match(/^grok-(\d+)(?:\.(\d+))?/);
122
+ if (!grokMatch) return 100_000_000 + tieBreakerSnapshot(modelId);
123
+ const major = Number.parseInt(grokMatch[1], 10);
124
+ const minor = grokMatch[2] ? Number.parseInt(grokMatch[2], 10) : 0;
125
+ let score = (major * 100 + minor) * 1_000_000_000;
126
+ if (local.includes("non-reasoning")) score -= 100_000;
127
+ else if (local.includes("reasoning")) score += 200_000;
128
+ if (local.includes("fast")) score -= 50_000;
129
+ if (local.includes("beta")) score -= 500_000;
130
+ if (local.includes("code")) score += 100_000;
131
+ score += tieBreakerSnapshot(modelId);
132
+ return score;
133
+ }
134
+
135
+ function deepseekPreferenceScore(modelId) {
136
+ const local = stripPrefix("deepseek", modelId);
137
+ if (local.includes("reasoner")) return 600_000_000;
138
+ if (local.includes("chat")) return 500_000_000;
139
+ return 100_000_000 + tieBreakerSnapshot(modelId);
140
+ }
141
+
142
+ function googlePreferenceScore(modelId) {
143
+ const local = stripPrefix("google", modelId).replace(/^google-vertex\//, "");
144
+ const gemini = local.match(/gemini-(\d+)(?:\.(\d+))?/);
145
+ if (!gemini) return 100_000_000 + tieBreakerSnapshot(modelId);
146
+ const major = Number.parseInt(gemini[1], 10);
147
+ const minor = gemini[2] ? Number.parseInt(gemini[2], 10) : 0;
148
+ let score = (major * 100 + minor) * 1_000_000_000;
149
+ if (local.includes("pro")) score += 200_000_000;
150
+ else if (local.includes("ultra")) score += 300_000_000;
151
+ else if (local.includes("flash")) score += 100_000_000;
152
+ else if (local.includes("nano")) score += 50_000_000;
153
+ if (local.includes("preview") || local.includes("experimental")) score -= 50_000_000;
154
+ if (local.includes("thinking")) score += 10_000_000;
155
+ if (local.includes("latest")) score += 5_000_000;
156
+ score += tieBreakerSnapshot(modelId);
157
+ return score;
158
+ }
159
+
160
+ function extractParamCountBonus(local) {
161
+ const m = local.match(/(\d+)b(?:\b|-)/i);
162
+ if (!m) return 0;
163
+ const b = Number.parseInt(m[1], 10);
164
+ return Math.min(b, 2000) * 100;
165
+ }
166
+
91
167
  function genericPreferenceScore(provider, modelId) {
92
168
  const local = stripPrefix(provider, modelId);
93
169
  let score = tieBreakerSnapshot(modelId);
94
170
  if (local.includes("latest")) score += 500_000_000;
171
+ if (local.includes("pro") || local.includes("large")) score += 100_000_000;
95
172
  if (local.includes("preview") || local.includes("deprecated")) score -= 200_000_000;
173
+ if (local.includes("beta")) score -= 50_000_000;
174
+ const verMatch = local.match(/(?:^|[a-z-])(\d+)(?:\.(\d+))?/);
175
+ if (verMatch) {
176
+ const maj = Number.parseInt(verMatch[1], 10);
177
+ const min = verMatch[2] ? Number.parseInt(verMatch[2], 10) : 0;
178
+ if (maj <= 99) {
179
+ score += (maj * 100 + min) * 1_000_000;
180
+ }
181
+ }
182
+ score += extractParamCountBonus(local);
96
183
  return score;
97
184
  }
98
185
 
@@ -111,6 +198,12 @@ export function modelPreferenceScore(provider, modelId) {
111
198
  score += anthropicPreferenceScore(id);
112
199
  } else if (provider === "openai" || provider === "openai-codex") {
113
200
  score += openaiPreferenceScore(id);
201
+ } else if (provider === "google" || provider === "google-vertex") {
202
+ score += googlePreferenceScore(id);
203
+ } else if (provider === "xai") {
204
+ score += xaiPreferenceScore(id);
205
+ } else if (provider === "deepseek") {
206
+ score += deepseekPreferenceScore(id);
114
207
  } else {
115
208
  score += genericPreferenceScore(provider, id);
116
209
  }
@@ -71,9 +71,18 @@ function commandExists(cmd) {
71
71
  }
72
72
  }
73
73
 
74
+ function stripAnsi(text) {
75
+ if (typeof text !== "string") return text;
76
+ return text
77
+ .replace(/\x1b\[[0-9;]*[a-zA-Z]/g, "")
78
+ .replace(/\x1b\][^\x07\x1b]*(?:\x07|\x1b\\)/g, "")
79
+ .replace(/\x1b[^[\]]/g, "")
80
+ .replace(/\x1b/g, "");
81
+ }
82
+
74
83
  function getCommandOutput(cmd) {
75
84
  try {
76
- return execSync(cmd, { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"], shell: true }).trim();
85
+ return execSync(cmd, { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"], shell: true, maxBuffer: 50 * 1024 * 1024 }).trim();
77
86
  } catch {
78
87
  return null;
79
88
  }
@@ -1725,6 +1734,17 @@ function loadWizardLlmCatalog() {
1725
1734
  "mistral",
1726
1735
  "google",
1727
1736
  "google-vertex",
1737
+ "xai",
1738
+ "deepseek",
1739
+ "together",
1740
+ "perplexity",
1741
+ "amazon-bedrock",
1742
+ "vercel-ai-gateway",
1743
+ "minimax",
1744
+ "moonshot",
1745
+ "nvidia",
1746
+ "qwen",
1747
+ "cerebras",
1728
1748
  ]);
1729
1749
  const fallback = {
1730
1750
  source: "fallback",
@@ -1737,6 +1757,30 @@ function loadWizardLlmCatalog() {
1737
1757
  id: "openai",
1738
1758
  models: [{ id: "openai/gpt-5.4", name: "GPT-5.4" }],
1739
1759
  },
1760
+ {
1761
+ id: "xai",
1762
+ models: [{ id: "xai/grok-4", name: "Grok 4" }],
1763
+ },
1764
+ {
1765
+ id: "deepseek",
1766
+ models: [{ id: "deepseek/deepseek-chat", name: "DeepSeek Chat (V3.2)" }],
1767
+ },
1768
+ {
1769
+ id: "google",
1770
+ models: [{ id: "google/gemini-2.5-flash", name: "Gemini 2.5 Flash" }],
1771
+ },
1772
+ {
1773
+ id: "groq",
1774
+ models: [{ id: "groq/llama-4-scout-17b-16e-instruct", name: "Llama 4 Scout" }],
1775
+ },
1776
+ {
1777
+ id: "openrouter",
1778
+ models: [{ id: "openrouter/anthropic/claude-sonnet-4-6", name: "Claude Sonnet 4.6 (via OpenRouter)" }],
1779
+ },
1780
+ {
1781
+ id: "mistral",
1782
+ models: [{ id: "mistral/mistral-large-latest", name: "Mistral Large" }],
1783
+ },
1740
1784
  ],
1741
1785
  };
1742
1786
 
@@ -1748,8 +1792,10 @@ function loadWizardLlmCatalog() {
1748
1792
  const raw = execSync("openclaw models list --all --json", {
1749
1793
  encoding: "utf-8",
1750
1794
  stdio: ["ignore", "pipe", "pipe"],
1795
+ maxBuffer: 50 * 1024 * 1024,
1796
+ timeout: 30_000,
1751
1797
  });
1752
- const parsed = JSON.parse(raw);
1798
+ const parsed = JSON.parse(stripAnsi(raw));
1753
1799
  const models = Array.isArray(parsed?.models) ? parsed.models : [];
1754
1800
  const providerMap = new Map();
1755
1801
  for (const entry of models) {
@@ -1791,9 +1837,15 @@ function loadWizardLlmCatalog() {
1791
1837
  generatedAt: new Date().toISOString(),
1792
1838
  };
1793
1839
  } catch (err) {
1840
+ const detail = err?.message || String(err);
1841
+ const isBufferErr = detail.includes("maxBuffer") || detail.includes("ENOBUFS");
1842
+ const hint = isBufferErr
1843
+ ? " (stdout exceeded buffer — OpenClaw model catalog may have grown; this version raises the limit)"
1844
+ : "";
1845
+ console.error(`[traderclaw] loadWizardLlmCatalog failed${hint}: ${detail.slice(0, 500)}`);
1794
1846
  return {
1795
1847
  ...fallback,
1796
- warning: `openclaw_models_list_failed: ${err?.message || String(err)}`,
1848
+ warning: `openclaw_models_list_failed: ${detail}`,
1797
1849
  };
1798
1850
  }
1799
1851
  }
@@ -2154,7 +2206,11 @@ function wizardHtml(defaults) {
2154
2206
  }
2155
2207
  setSelectOptions(llmProviderEl, providers, "${defaults.llmProvider}");
2156
2208
  refreshModelOptions("${defaults.llmModel}");
2157
- setLlmCatalogReady(true, "LLM providers loaded. Select provider and paste credential to continue. Model selection is optional.");
2209
+ const isFallback = llmCatalog.source === "fallback";
2210
+ const catalogMsg = isFallback
2211
+ ? "Showing safe defaults only (could not load full OpenClaw catalog" + (llmCatalog.warning ? ": " + llmCatalog.warning : "") + "). These providers still work — pick one and paste your credential."
2212
+ : "LLM providers loaded. Select provider and paste credential to continue. Model selection is optional.";
2213
+ setLlmCatalogReady(true, catalogMsg, isFallback);
2158
2214
  } catch (err) {
2159
2215
  setLlmCatalogReady(false, "Failed to load LLM providers. Check OpenClaw and reload this page.", true);
2160
2216
  manualEl.textContent = "Failed to load LLM provider catalog: " + (err && err.message ? err.message : String(err));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "solana-traderclaw",
3
- "version": "1.0.45",
3
+ "version": "1.0.47",
4
4
  "description": "TraderClaw V1-Upgraded — Solana trading for OpenClaw with intelligence lab, tool envelopes, prompt scrubbing, read-only X social intel, and split skill docs",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",