openclaw-openviking-setup-helper 0.2.16-dev.4 → 0.3.0-beta.10

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 +162 -24
  2. package/package.json +1 -1
package/install.js CHANGED
@@ -97,9 +97,9 @@ let rollbackLastUpgrade = false;
97
97
  let showCurrentVersion = false;
98
98
 
99
99
  const selectedMode = "remote";
100
- let remoteBaseUrl = "http://127.0.0.1:1933";
101
- let remoteApiKey = "";
102
- let remoteAgentPrefix = "";
100
+ let remoteBaseUrl = (process.env.OPENVIKING_BASE_URL || "http://127.0.0.1:1933").trim();
101
+ let remoteApiKey = (process.env.OPENVIKING_API_KEY || "").trim();
102
+ let remoteAgentPrefix = (process.env.OPENVIKING_AGENT_PREFIX || "").trim();
103
103
  let upgradeRuntimeConfig = null;
104
104
  let installedUpgradeState = null;
105
105
  let upgradeAudit = null;
@@ -874,8 +874,9 @@ function extractRuntimeConfigFromPluginEntry(entryConfig) {
874
874
  if (typeof entryConfig.apiKey === "string" && entryConfig.apiKey.trim()) {
875
875
  runtime.apiKey = entryConfig.apiKey;
876
876
  }
877
- if (typeof entryConfig.agent_prefix === "string" && entryConfig.agent_prefix.trim()) {
878
- runtime.agent_prefix = entryConfig.agent_prefix.trim();
877
+ const prefix = entryConfig.agent_prefix || entryConfig.agentId;
878
+ if (typeof prefix === "string" && prefix.trim()) {
879
+ runtime.agent_prefix = prefix.trim();
879
880
  }
880
881
  return runtime;
881
882
  }
@@ -1417,6 +1418,7 @@ async function configureOpenClawPlugin({
1417
1418
  const pluginSlot = resolvedPluginSlot;
1418
1419
 
1419
1420
  const ocEnv = getOpenClawEnv();
1421
+ const needWorkdirFlag = OPENCLAW_DIR !== DEFAULT_OPENCLAW_DIR;
1420
1422
 
1421
1423
  const oc = async (args) => {
1422
1424
  const result = await runCapture("openclaw", args, { env: ocEnv, shell: IS_WIN });
@@ -1427,24 +1429,59 @@ async function configureOpenClawPlugin({
1427
1429
  return result;
1428
1430
  };
1429
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
+
1430
1456
  if (!preserveExistingConfig) {
1431
1457
  await scrubStaleOpenClawPluginRegistration();
1432
1458
  }
1433
1459
 
1434
- // Enable plugin (files already deployed to extensions dir by deployPlugin)
1435
- await oc(["plugins", "enable", pluginId]);
1436
- if (claimSlot) {
1437
- await oc(["config", "set", `plugins.slots.${pluginSlot}`, 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
+ }
1438
1470
  } else {
1439
- warn(
1440
- tr(
1441
- `Skipped claiming plugins.slots.${pluginSlot}; it is currently owned by another plugin.`,
1442
- `已跳过设置 plugins.slots.${pluginSlot},当前该 slot 由其他插件占用。`,
1443
- ),
1444
- );
1471
+ info(tr("Using direct config write for non-default workdir", "非默认目录,使用直接配置写入"));
1472
+ const cfg = await readCfg();
1473
+ await ensurePluginRegistered(cfg);
1474
+ await writeCfg(cfg);
1445
1475
  }
1446
1476
 
1447
1477
  if (preserveExistingConfig) {
1478
+ if (claimSlot) {
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);
1484
+ }
1448
1485
  info(
1449
1486
  tr(
1450
1487
  `Preserved existing plugin runtime config for ${pluginId}`,
@@ -1454,28 +1491,129 @@ async function configureOpenClawPlugin({
1454
1491
  return;
1455
1492
  }
1456
1493
 
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;
1501
+ }
1502
+ await writeCfg(cfg);
1503
+ };
1504
+
1505
+ // Legacy (memory) plugins: direct JSON write
1506
+ if (resolvedPluginKind === "memory") {
1507
+ const effectiveRuntimeConfig = runtimeConfig || {
1508
+ baseUrl: remoteBaseUrl,
1509
+ apiKey: remoteApiKey,
1510
+ };
1511
+ const pluginConfig = {
1512
+ baseUrl: effectiveRuntimeConfig.baseUrl || remoteBaseUrl,
1513
+ targetUri: "viking://user/memories",
1514
+ autoRecall: true,
1515
+ autoCapture: true,
1516
+ };
1517
+ if (effectiveRuntimeConfig.apiKey) {
1518
+ pluginConfig.apiKey = effectiveRuntimeConfig.apiKey;
1519
+ }
1520
+ await writeConfigDirect(pluginConfig, claimSlot ? pluginId : null);
1521
+ info(tr("OpenClaw plugin configured (legacy mode)", "OpenClaw 插件配置完成(旧版模式)"));
1522
+ return;
1523
+ }
1524
+
1525
+ // Current (context-engine) plugins: delegate to `openclaw openviking setup --json`
1526
+ // This reuses the same validation logic (health check, version compat, root key
1527
+ // detection, slot protection, ensureInstallRecord) from commands/setup.ts
1457
1528
  const effectiveRuntimeConfig = runtimeConfig || {
1458
1529
  baseUrl: remoteBaseUrl,
1459
1530
  apiKey: remoteApiKey,
1460
1531
  agent_prefix: remoteAgentPrefix,
1461
1532
  };
1462
1533
 
1463
- await oc(["config", "set", `plugins.entries.${pluginId}.config.baseUrl`, effectiveRuntimeConfig.baseUrl || remoteBaseUrl]);
1534
+ const setupArgs = needWorkdirFlag
1535
+ ? ["--workdir", OPENCLAW_DIR, "openviking", "setup"]
1536
+ : ["openviking", "setup"];
1537
+ setupArgs.push("--base-url", effectiveRuntimeConfig.baseUrl || remoteBaseUrl);
1538
+ setupArgs.push("--json");
1464
1539
  if (effectiveRuntimeConfig.apiKey) {
1465
- await oc(["config", "set", `plugins.entries.${pluginId}.config.apiKey`, effectiveRuntimeConfig.apiKey]);
1540
+ setupArgs.push("--api-key", effectiveRuntimeConfig.apiKey);
1466
1541
  }
1467
1542
  if (effectiveRuntimeConfig.agent_prefix) {
1468
- await oc(["config", "set", `plugins.entries.${pluginId}.config.agent_prefix`, effectiveRuntimeConfig.agent_prefix]);
1543
+ setupArgs.push("--agent-id", effectiveRuntimeConfig.agent_prefix);
1544
+ }
1545
+ if (claimSlot) {
1546
+ setupArgs.push("--force-slot");
1547
+ }
1548
+ if (installYes) {
1549
+ setupArgs.push("--allow-offline");
1469
1550
  }
1470
1551
 
1471
- // Legacy (memory) plugins need explicit targetUri/autoRecall/autoCapture (new version has defaults in config.ts)
1472
- if (resolvedPluginKind === "memory") {
1473
- await oc(["config", "set", `plugins.entries.${pluginId}.config.targetUri`, "viking://user/memories"]);
1474
- await oc(["config", "set", `plugins.entries.${pluginId}.config.autoRecall`, "true", "--json"]);
1475
- await oc(["config", "set", `plugins.entries.${pluginId}.config.autoCapture`, "true", "--json"]);
1552
+ info(tr(
1553
+ "Delegating configuration to: openclaw openviking setup --json",
1554
+ "委托配置给: openclaw openviking setup --json",
1555
+ ));
1556
+
1557
+ const setupResult = await runCapture("openclaw", setupArgs, { env: ocEnv, shell: IS_WIN });
1558
+
1559
+ let parsed = null;
1560
+ try {
1561
+ parsed = JSON.parse(setupResult.out.trim());
1562
+ } catch {
1563
+ // If JSON parse fails, fall back to checking exit code
1476
1564
  }
1477
1565
 
1478
- info(tr("OpenClaw plugin configured", "OpenClaw 插件配置完成"));
1566
+ if (parsed) {
1567
+ if (parsed.success) {
1568
+ info(tr("OpenClaw plugin configured via setup", "OpenClaw 插件通过 setup 配置完成"));
1569
+ if (parsed.health?.ok) {
1570
+ info(tr(
1571
+ `Server health: OK${parsed.health.version ? ` (version: ${parsed.health.version})` : ""}`,
1572
+ `服务端健康: OK${parsed.health.version ? `(版本: ${parsed.health.version})` : ""}`,
1573
+ ));
1574
+ }
1575
+ if (parsed.health?.compatibility === "server_too_old") {
1576
+ warn(tr(
1577
+ "Server version may be too old for this plugin version",
1578
+ "服务端版本可能低于此插件版本要求",
1579
+ ));
1580
+ }
1581
+ if (parsed.slot?.activated) {
1582
+ info(tr(`contextEngine slot activated`, `contextEngine slot 已激活`));
1583
+ }
1584
+ } else {
1585
+ // Setup returned success: false
1586
+ if (parsed.action === "slot_blocked") {
1587
+ warn(tr(
1588
+ `Config saved but contextEngine slot is owned by "${parsed.slot?.previousOwner}". Use --force-slot to override.`,
1589
+ `配置已保存,但 contextEngine slot 被 "${parsed.slot?.previousOwner}" 占用。使用 --force-slot 覆盖。`,
1590
+ ));
1591
+ } else {
1592
+ err(tr(
1593
+ `Setup failed: ${parsed.error || "unknown error"}`,
1594
+ `配置失败: ${parsed.error || "未知错误"}`,
1595
+ ));
1596
+ }
1597
+ }
1598
+ } else if (setupResult.code !== 0) {
1599
+ // JSON parse failed and non-zero exit — setup CLI not available (old plugin version)
1600
+ warn(tr(
1601
+ `openclaw openviking setup exited with code ${setupResult.code}. Falling back to direct JSON config write.`,
1602
+ `openclaw openviking setup 退出码 ${setupResult.code},回退到直接写入 JSON 配置。`,
1603
+ ));
1604
+ const pluginConfig = {
1605
+ baseUrl: effectiveRuntimeConfig.baseUrl || remoteBaseUrl,
1606
+ apiKey: effectiveRuntimeConfig.apiKey || "",
1607
+ agent_prefix: effectiveRuntimeConfig.agent_prefix || "",
1608
+ };
1609
+ await writeConfigDirect(pluginConfig, claimSlot ? pluginId : null);
1610
+ info(tr(
1611
+ `OpenClaw plugin configured (direct write): baseUrl=${pluginConfig.baseUrl}, apiKey=${pluginConfig.apiKey ? "***" : "(empty)"}, agent_prefix=${pluginConfig.agent_prefix || "(empty)"}`,
1612
+ `OpenClaw 插件配置完成(直接写入): baseUrl=${pluginConfig.baseUrl}, apiKey=${pluginConfig.apiKey ? "***" : "(空)"}, agent_prefix=${pluginConfig.agent_prefix || "(空)"}`,
1613
+ ));
1614
+ } else {
1615
+ info(tr("OpenClaw plugin configured", "OpenClaw 插件配置完成"));
1616
+ }
1479
1617
  }
1480
1618
 
1481
1619
  async function writeOpenvikingEnv() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openclaw-openviking-setup-helper",
3
- "version": "0.2.16-dev.4",
3
+ "version": "0.3.0-beta.10",
4
4
  "description": "Setup helper for installing OpenViking memory plugin into OpenClaw",
5
5
  "type": "module",
6
6
  "bin": {