openclaw-openviking-setup-helper 0.3.0-beta.8 → 0.3.0-beta.9

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.
Files changed (2) hide show
  1. package/install.js +76 -75
  2. package/package.json +1 -1
package/install.js CHANGED
@@ -1419,12 +1419,9 @@ async function configureOpenClawPlugin({
1419
1419
 
1420
1420
  const ocEnv = getOpenClawEnv();
1421
1421
  const needWorkdirFlag = OPENCLAW_DIR !== DEFAULT_OPENCLAW_DIR;
1422
- const workdirCmds = new Set(["config", "openviking", "status", "gateway", "logs"]);
1423
1422
 
1424
1423
  const oc = async (args) => {
1425
- const useWorkdir = needWorkdirFlag && args.length > 0 && workdirCmds.has(args[0]);
1426
- const fullArgs = useWorkdir ? ["--workdir", OPENCLAW_DIR, ...args] : args;
1427
- const result = await runCapture("openclaw", fullArgs, { env: ocEnv, shell: IS_WIN });
1424
+ const result = await runCapture("openclaw", args, { env: ocEnv, shell: IS_WIN });
1428
1425
  if (result.code !== 0) {
1429
1426
  const detail = result.err || result.out;
1430
1427
  throw new Error(`openclaw ${args.join(" ")} failed (exit code ${result.code})${detail ? `: ${detail}` : ""}`);
@@ -1432,16 +1429,58 @@ async function configureOpenClawPlugin({
1432
1429
  return result;
1433
1430
  };
1434
1431
 
1432
+ // Direct file manipulation for config (reliable across all OpenClaw versions and --workdir scenarios).
1433
+ // OpenClaw CLI's --workdir / OPENCLAW_STATE_DIR support is inconsistent, so we read/write openclaw.json directly.
1434
+ const configPath = getOpenClawConfigPath();
1435
+ const readCfg = async () => {
1436
+ if (!existsSync(configPath)) return {};
1437
+ try { return JSON.parse(await readFile(configPath, "utf8")); } catch { return {}; }
1438
+ };
1439
+ const writeCfg = async (cfg) => {
1440
+ const out = JSON.stringify(cfg, null, 2) + "\n";
1441
+ const tmp = `${configPath}.ov-install-tmp.${process.pid}`;
1442
+ await writeFile(tmp, out, "utf8");
1443
+ await rename(tmp, configPath);
1444
+ };
1445
+ const ensurePluginRegistered = async (cfg) => {
1446
+ if (!cfg.plugins) cfg.plugins = {};
1447
+ const p = cfg.plugins;
1448
+ if (!p.entries) p.entries = {};
1449
+ if (!p.entries[pluginId]) p.entries[pluginId] = {};
1450
+ if (!p.entries[pluginId].config) p.entries[pluginId].config = {};
1451
+ if (!Array.isArray(p.allow)) p.allow = [];
1452
+ if (!p.allow.includes(pluginId)) p.allow.push(pluginId);
1453
+ return cfg;
1454
+ };
1455
+
1435
1456
  if (!preserveExistingConfig) {
1436
1457
  await scrubStaleOpenClawPluginRegistration();
1437
1458
  }
1438
1459
 
1439
- // Enable plugin (files already deployed to extensions dir by deployPlugin)
1440
- await oc(["plugins", "enable", pluginId]);
1460
+ // Enable plugin: try CLI first (default path), fall back to direct file for --workdir
1461
+ if (!needWorkdirFlag) {
1462
+ try {
1463
+ await oc(["plugins", "enable", pluginId]);
1464
+ } catch (_e) {
1465
+ info(tr("plugins enable via CLI failed, registering directly", "CLI plugins enable 失败,直接注册"));
1466
+ const cfg = await readCfg();
1467
+ await ensurePluginRegistered(cfg);
1468
+ await writeCfg(cfg);
1469
+ }
1470
+ } else {
1471
+ info(tr("Using direct config write for non-default workdir", "非默认目录,使用直接配置写入"));
1472
+ const cfg = await readCfg();
1473
+ await ensurePluginRegistered(cfg);
1474
+ await writeCfg(cfg);
1475
+ }
1441
1476
 
1442
1477
  if (preserveExistingConfig) {
1443
1478
  if (claimSlot) {
1444
- await oc(["config", "set", `plugins.slots.${pluginSlot}`, pluginId]);
1479
+ const cfg = await readCfg();
1480
+ if (!cfg.plugins) cfg.plugins = {};
1481
+ if (!cfg.plugins.slots) cfg.plugins.slots = {};
1482
+ cfg.plugins.slots[pluginSlot] = pluginId;
1483
+ await writeCfg(cfg);
1445
1484
  }
1446
1485
  info(
1447
1486
  tr(
@@ -1452,29 +1491,33 @@ async function configureOpenClawPlugin({
1452
1491
  return;
1453
1492
  }
1454
1493
 
1455
- // Legacy (memory) plugins still use direct config set
1456
- if (resolvedPluginKind === "memory") {
1457
- if (claimSlot) {
1458
- try { await oc(["config", "set", `plugins.slots.${pluginSlot}`, pluginId]); } catch (_e) {
1459
- warn(tr("Could not activate slot for legacy plugin", "无法为旧版插件激活 slot"));
1460
- }
1494
+ const writeConfigDirect = async (pluginConfig, slotValue) => {
1495
+ const cfg = await readCfg();
1496
+ await ensurePluginRegistered(cfg);
1497
+ Object.assign(cfg.plugins.entries[pluginId].config, pluginConfig);
1498
+ if (slotValue) {
1499
+ if (!cfg.plugins.slots) cfg.plugins.slots = {};
1500
+ cfg.plugins.slots[pluginSlot] = slotValue;
1461
1501
  }
1502
+ await writeCfg(cfg);
1503
+ };
1504
+
1505
+ // Legacy (memory) plugins: direct JSON write
1506
+ if (resolvedPluginKind === "memory") {
1462
1507
  const effectiveRuntimeConfig = runtimeConfig || {
1463
1508
  baseUrl: remoteBaseUrl,
1464
1509
  apiKey: remoteApiKey,
1465
- agent_prefix: remoteAgentPrefix,
1466
1510
  };
1467
- const trySet = async (k, v) => {
1468
- try { await oc(["config", "set", `plugins.entries.${pluginId}.config.${k}`, v]); }
1469
- catch (_e) { warn(tr(`Could not set ${k} for legacy plugin`, `无法为旧版插件设置 ${k}`)); }
1511
+ const pluginConfig = {
1512
+ baseUrl: effectiveRuntimeConfig.baseUrl || remoteBaseUrl,
1513
+ targetUri: "viking://user/memories",
1514
+ autoRecall: true,
1515
+ autoCapture: true,
1470
1516
  };
1471
- await trySet("baseUrl", effectiveRuntimeConfig.baseUrl || remoteBaseUrl);
1472
1517
  if (effectiveRuntimeConfig.apiKey) {
1473
- await trySet("apiKey", effectiveRuntimeConfig.apiKey);
1518
+ pluginConfig.apiKey = effectiveRuntimeConfig.apiKey;
1474
1519
  }
1475
- await trySet("targetUri", "viking://user/memories");
1476
- try { await oc(["config", "set", `plugins.entries.${pluginId}.config.autoRecall`, "true", "--json"]); } catch (_e) { /* optional */ }
1477
- try { await oc(["config", "set", `plugins.entries.${pluginId}.config.autoCapture`, "true", "--json"]); } catch (_e) { /* optional */ }
1520
+ await writeConfigDirect(pluginConfig, claimSlot ? pluginId : null);
1478
1521
  info(tr("OpenClaw plugin configured (legacy mode)", "OpenClaw 插件配置完成(旧版模式)"));
1479
1522
  return;
1480
1523
  }
@@ -1553,68 +1596,26 @@ async function configureOpenClawPlugin({
1553
1596
  }
1554
1597
  }
1555
1598
  } else if (setupResult.code !== 0) {
1556
- // JSON parse failed and non-zero exit
1599
+ // JSON parse failed and non-zero exit — setup CLI not available (old plugin version)
1557
1600
  warn(tr(
1558
- `openclaw openviking setup exited with code ${setupResult.code}. Falling back to direct config.`,
1559
- `openclaw openviking setup 退出码 ${setupResult.code},回退到直接配置。`,
1601
+ `openclaw openviking setup exited with code ${setupResult.code}. Falling back to direct JSON config write.`,
1602
+ `openclaw openviking setup 退出码 ${setupResult.code},回退到直接写入 JSON 配置。`,
1560
1603
  ));
1561
- // Fallback: direct config set (for backward compat if setup CLI not available)
1562
- // Each field is wrapped individually so one schema mismatch does not abort the rest.
1563
- let fallbackOk = true;
1564
- const tryConfigSet = async (key, value, altKey) => {
1565
- try {
1566
- await oc(["config", "set", `plugins.entries.${pluginId}.config.${key}`, value]);
1567
- } catch (_e) {
1568
- if (altKey) {
1569
- try {
1570
- await oc(["config", "set", `plugins.entries.${pluginId}.config.${altKey}`, value]);
1571
- return;
1572
- } catch (_e2) { /* fall through to warn */ }
1573
- }
1574
- fallbackOk = false;
1575
- warn(tr(
1576
- `Could not set config field "${key}": schema validation failed (plugin version may not support this field)`,
1577
- `无法设置配置字段 "${key}":schema 校验失败(插件版本可能不支持此字段)`,
1578
- ));
1579
- }
1604
+ const pluginConfig = {
1605
+ baseUrl: effectiveRuntimeConfig.baseUrl || remoteBaseUrl,
1580
1606
  };
1581
-
1582
- await tryConfigSet("baseUrl", effectiveRuntimeConfig.baseUrl || remoteBaseUrl);
1583
1607
  if (effectiveRuntimeConfig.apiKey) {
1584
- await tryConfigSet("apiKey", effectiveRuntimeConfig.apiKey);
1608
+ pluginConfig.apiKey = effectiveRuntimeConfig.apiKey;
1585
1609
  }
1586
1610
  if (effectiveRuntimeConfig.agent_prefix) {
1587
- await tryConfigSet("agent_prefix", effectiveRuntimeConfig.agent_prefix, "agentId");
1588
- }
1589
- if (claimSlot) {
1590
- try {
1591
- await oc(["config", "set", `plugins.slots.${pluginSlot}`, pluginId]);
1592
- } catch (_e) {
1593
- fallbackOk = false;
1594
- warn(tr(
1595
- "Could not activate contextEngine slot",
1596
- "无法激活 contextEngine slot",
1597
- ));
1598
- }
1599
- }
1600
- if (fallbackOk) {
1601
- info(tr("OpenClaw plugin configured (fallback)", "OpenClaw 插件配置完成(回退模式)"));
1602
- } else {
1603
- warn(tr(
1604
- "OpenClaw plugin partially configured (fallback). Some fields could not be set. Run `openclaw openviking setup` to complete configuration.",
1605
- "OpenClaw 插件部分配置完成(回退模式)。部分字段未能设置,请运行 `openclaw openviking setup` 完善配置。",
1606
- ));
1607
- }
1608
- if (effectiveRuntimeConfig.apiKey) {
1609
- warn(tr(
1610
- "Note: Root API key detection, accountId/userId tenant context, and server version compatibility checks are only available via `openclaw openviking setup`. If you are using a root API key, please upgrade the plugin and re-run setup.",
1611
- "提示:Root API Key 检测、accountId/userId 租户上下文、服务端版本兼容性检查仅在 `openclaw openviking setup` 中可用。如果您使用的是 root API key,请升级插件后重新执行 setup。",
1612
- ));
1611
+ pluginConfig.agent_prefix = effectiveRuntimeConfig.agent_prefix;
1613
1612
  }
1613
+ await writeConfigDirect(pluginConfig, claimSlot ? pluginId : null);
1614
+ info(tr("OpenClaw plugin configured (direct write)", "OpenClaw 插件配置完成(直接写入)"));
1614
1615
  if (effectiveRuntimeConfig.apiKey) {
1615
1616
  info(tr(
1616
- "Note: If using a root API key, run `openclaw openviking setup` to configure accountId/userId (required for tenant isolation).",
1617
- "提示:如果使用的是 root API key,请运行 `openclaw openviking setup` 配置 accountId/userId(多租户隔离必需)。",
1617
+ "Note: Root API key detection and tenant context are only available via `openclaw openviking setup`. If using a root API key, upgrade the plugin and re-run setup.",
1618
+ "提示:Root API Key 检测和租户上下文仅在 `openclaw openviking setup` 中可用。如果使用 root API key,请升级插件后重新执行 setup。",
1618
1619
  ));
1619
1620
  }
1620
1621
  } else {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openclaw-openviking-setup-helper",
3
- "version": "0.3.0-beta.8",
3
+ "version": "0.3.0-beta.9",
4
4
  "description": "Setup helper for installing OpenViking memory plugin into OpenClaw",
5
5
  "type": "module",
6
6
  "bin": {