solana-traderclaw 1.0.31 → 1.0.32

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.
@@ -203,6 +203,29 @@ function gatewayModeUnsetRemediation() {
203
203
  ].join("\n");
204
204
  }
205
205
 
206
+ function gatewayConfigValidationRemediation() {
207
+ return [
208
+ "OpenClaw could not load or validate ~/.openclaw/openclaw.json after plugins are enabled (often an Ajv/schema compile error in the OpenClaw CLI, not invalid JSON syntax).",
209
+ "The first `openclaw config validate` in this installer runs before plugins install; validation must be re-run once plugin schemas are registered — that is why this can appear only at gateway.",
210
+ "On the VPS, try in order:",
211
+ "1) openclaw --version",
212
+ "2) npm install -g openclaw@latest",
213
+ "3) openclaw config validate",
214
+ "4) openclaw plugins doctor",
215
+ "5) cp ~/.openclaw/openclaw.json ~/.openclaw/openclaw.json.bak.$(date +%s) || true",
216
+ "If it still fails, report the OpenClaw version plus output of steps 3–4 to OpenClaw/TraderClaw support (redact secrets).",
217
+ ].join("\n");
218
+ }
219
+
220
+ function isOpenClawConfigSchemaFailure(text) {
221
+ const t = String(text || "").toLowerCase();
222
+ return (
223
+ t.includes("ajv implementation")
224
+ || t.includes("validatejsonschemavalue")
225
+ || (t.includes("failed to read config") && t.includes("ajv"))
226
+ );
227
+ }
228
+
206
229
  function runCommandWithEvents(cmd, args = [], opts = {}) {
207
230
  return new Promise((resolve, reject) => {
208
231
  const { onEvent, ...spawnOpts } = opts;
@@ -1114,9 +1137,10 @@ function resolveLlmModelSelection(provider, requestedModel) {
1114
1137
  }
1115
1138
 
1116
1139
  /**
1117
- * OpenClaw 2026+ validates `agents.defaults` with Zod/Ajv: if `defaults` exists it must include
1118
- * `heartbeat` and `model` objects. `openclaw plugins install/enable` can merge config and drop
1119
- * these keys, which surfaces as obscure stack errors (e.g. "ajv implementation error") on the next CLI call.
1140
+ * OpenClaw 2026+ expects `agents.defaults.heartbeat` as an object when `defaults` exists; plugin merges
1141
+ * sometimes drop it. We only add `heartbeat: {}` here do NOT add `model: {}` when `model` is absent:
1142
+ * many schemas require `model.primary` whenever `model` is present; an empty model object caused Ajv
1143
+ * failures after hardening (regression for installs where the plugin stripped `model` but left defaults).
1120
1144
  */
1121
1145
  function ensureAgentsDefaultsSchemaCompat(config) {
1122
1146
  if (!config || typeof config !== "object") return;
@@ -1125,8 +1149,9 @@ function ensureAgentsDefaultsSchemaCompat(config) {
1125
1149
  if (!config.agents.defaults.heartbeat || typeof config.agents.defaults.heartbeat !== "object") {
1126
1150
  config.agents.defaults.heartbeat = {};
1127
1151
  }
1128
- if (!config.agents.defaults.model || typeof config.agents.defaults.model !== "object") {
1129
- config.agents.defaults.model = {};
1152
+ const m = config.agents.defaults.model;
1153
+ if (m !== undefined && m !== null && (typeof m !== "object" || Array.isArray(m))) {
1154
+ delete config.agents.defaults.model;
1130
1155
  }
1131
1156
  }
1132
1157
 
@@ -1189,6 +1214,9 @@ function configureOpenClawLlmProvider({ provider, model, credential }, configPat
1189
1214
  if (!config.agents) config.agents = {};
1190
1215
  if (!config.agents.defaults) config.agents.defaults = {};
1191
1216
  ensureAgentsDefaultsSchemaCompat(config);
1217
+ if (!config.agents.defaults.model || typeof config.agents.defaults.model !== "object") {
1218
+ config.agents.defaults.model = {};
1219
+ }
1192
1220
  config.agents.defaults.model.primary = model;
1193
1221
 
1194
1222
  mkdirSync(CONFIG_DIR, { recursive: true });
@@ -1643,6 +1671,19 @@ export class InstallerStepEngine {
1643
1671
  await this.runStep("tailscale_up", "Connecting Tailscale", async () => this.runTailscaleUp());
1644
1672
  }
1645
1673
  if (!this.options.skipGatewayBootstrap) {
1674
+ await this.runStep("openclaw_config_validate", "Validating OpenClaw config (with plugins)", async () => {
1675
+ normalizeOpenClawConfigFileShape(CONFIG_FILE);
1676
+ try {
1677
+ await this.runWithPrivilegeGuidance("openclaw_config_validate", "openclaw", ["config", "validate"]);
1678
+ } catch (err) {
1679
+ const blob = `${err?.message || ""}\n${err?.stderr || ""}\n${err?.stdout || ""}`;
1680
+ if (isOpenClawConfigSchemaFailure(blob)) {
1681
+ throw new Error(gatewayConfigValidationRemediation());
1682
+ }
1683
+ throw err;
1684
+ }
1685
+ return { ok: true };
1686
+ });
1646
1687
  await this.runStep("gateway_bootstrap", "Starting OpenClaw gateway and Funnel", async () => {
1647
1688
  try {
1648
1689
  normalizeOpenClawConfigFileShape(CONFIG_FILE);
@@ -1667,6 +1708,9 @@ export class InstallerStepEngine {
1667
1708
  }
1668
1709
  throw new Error(gatewayTimeoutRemediation());
1669
1710
  }
1711
+ if (isOpenClawConfigSchemaFailure(text)) {
1712
+ throw new Error(gatewayConfigValidationRemediation());
1713
+ }
1670
1714
  throw err;
1671
1715
  }
1672
1716
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "solana-traderclaw",
3
- "version": "1.0.31",
3
+ "version": "1.0.32",
4
4
  "description": "TraderClaw V1 — autonomous Solana memecoin trading for OpenClaw (team edition: X/Twitter journal and engagement tools)",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",