@agentlayer.tech/wallet 0.1.74 → 0.1.75

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.
@@ -2,7 +2,7 @@
2
2
  "id": "agent-wallet",
3
3
  "name": "Agent Wallet",
4
4
  "description": "Official OpenClaw plugin bridge for the agent-wallet backends, including Solana, local BTC, and local EVM.",
5
- "version": "0.1.74",
5
+ "version": "0.1.75",
6
6
  "contracts": {
7
7
  "tools": [
8
8
  "agentlayer_autonomous_approve",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentlayertech/agent-wallet-plugin",
3
- "version": "0.1.74",
3
+ "version": "0.1.75",
4
4
  "description": "OpenClaw plugin bridge for the AgentLayer wallet runtime.",
5
5
  "type": "module",
6
6
  "license": "SEE LICENSE IN ../../../LICENSE",
package/CHANGELOG.md CHANGED
@@ -2,6 +2,32 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## v0.1.75 - 2026-07-11
6
+
7
+ - Added a persistent, non-secret ownership registry for OpenClaw, Hermes,
8
+ Codex, and Claude Code integrations. Explicit installs are now distinguishable
9
+ from unrelated external plugins across runtime upgrades.
10
+
11
+ - Fixed `wallet update` so managed framework integrations advance with the
12
+ verified `current` runtime. OpenClaw config and Hermes paths are repaired,
13
+ while Codex and Claude Code registrations and versioned caches are refreshed
14
+ through their host CLIs.
15
+
16
+ - Added guarded adoption for legacy AgentLayer installs. Existing integrations
17
+ are adopted only when their registration and plugin manifests both identify
18
+ AgentLayer; unowned symlinks and external plugins remain untouched.
19
+
20
+ - Added per-framework synchronization details to `wallet status` and
21
+ `wallet doctor`, including failed host registration and restart requirements.
22
+ npm-exec installs also refresh an already-installed stale global CLI without
23
+ making global installation mandatory.
24
+
25
+ - Expanded installer regression coverage for managed upgrades, unmanaged
26
+ integration preservation, global CLI refresh, host registration, and
27
+ hermetic framework/npm homes.
28
+
29
+ ## v0.1.74 - 2026-07-10
30
+
5
31
  - Added a guarded npm beta-promotion workflow that acceptance-tests the exact
6
32
  registry artifact, verifies its integrity, rejects downgrades, serializes with
7
33
  publish jobs, and restores the previous `latest` tag if verification fails.
package/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.74
1
+ 0.1.75
@@ -2,7 +2,7 @@
2
2
 
3
3
  # Keep in sync with package.json, pyproject.toml, and the npm installer version.
4
4
  # scripts/check_release_version.mjs enforces this on release.
5
- __version__ = "0.1.74"
5
+ __version__ = "0.1.75"
6
6
 
7
7
  __all__ = [
8
8
  "config",
@@ -2,7 +2,7 @@
2
2
  "id": "agent-wallet",
3
3
  "name": "Agent Wallet",
4
4
  "description": "Plugin-friendly wallet backend for OpenClaw agents with safe wallet tools and runtime instructions across Solana, local BTC, and local EVM.",
5
- "version": "0.1.74",
5
+ "version": "0.1.75",
6
6
  "skills": ["skills/wallet-operator"],
7
7
  "configSchema": {
8
8
  "type": "object",
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "openclaw-agent-wallet"
7
- version = "0.1.74"
7
+ version = "0.1.75"
8
8
  description = "Plugin-friendly wallet backend for OpenClaw agents"
9
9
  requires-python = ">=3.10"
10
10
  dependencies = [
@@ -392,6 +392,60 @@ function updateJournalPath(env = process.env) {
392
392
  return path.join(resolveRuntimeBase(env), "update-journal.json");
393
393
  }
394
394
 
395
+ function integrationRegistryPath(env = process.env) {
396
+ return path.join(resolveRuntimeBase(env), "integrations.json");
397
+ }
398
+
399
+ function readIntegrationRegistry(env = process.env) {
400
+ const payload = readJsonFile(integrationRegistryPath(env));
401
+ if (!payload || payload.schema_version !== 1 || typeof payload.integrations !== "object") {
402
+ return { schema_version: 1, integrations: {} };
403
+ }
404
+ return payload;
405
+ }
406
+
407
+ function recordManagedIntegration(name, details = {}, env = process.env) {
408
+ const registry = readIntegrationRegistry(env);
409
+ registry.integrations[name] = {
410
+ ...details,
411
+ managed: true,
412
+ installed_version: packageVersion,
413
+ updated_at: new Date().toISOString(),
414
+ };
415
+ registry.updated_at = new Date().toISOString();
416
+ writeJsonFileAtomic(integrationRegistryPath(env), registry);
417
+ return registry.integrations[name];
418
+ }
419
+
420
+ function managedIntegration(name, env = process.env) {
421
+ const entry = readIntegrationRegistry(env).integrations[name];
422
+ return entry && entry.managed === true ? entry : null;
423
+ }
424
+
425
+ function integrationSyncStatus(env = process.env) {
426
+ const active = activeVersion(env);
427
+ const registry = readIntegrationRegistry(env);
428
+ const integrations = Object.entries(registry.integrations)
429
+ .filter(([, entry]) => entry?.managed === true)
430
+ .sort(([left], [right]) => left.localeCompare(right))
431
+ .map(([name, entry]) => {
432
+ const versionInSync = active === null || entry.installed_version === active;
433
+ const registrationOk = entry.registration_ok !== false;
434
+ return {
435
+ name,
436
+ installed_version: entry.installed_version || null,
437
+ active_version: active,
438
+ in_sync: versionInSync && registrationOk,
439
+ registration_ok: registrationOk,
440
+ restart_required: Boolean(entry.restart_required),
441
+ };
442
+ });
443
+ return {
444
+ in_sync: integrations.every((entry) => entry.in_sync),
445
+ integrations,
446
+ };
447
+ }
448
+
395
449
  function writeUpdateJournal(state, details = {}, env = process.env) {
396
450
  writeJsonFile(updateJournalPath(env), {
397
451
  schema_version: 1,
@@ -944,6 +998,22 @@ function writeJsonFile(pathname, value) {
944
998
  fs.writeFileSync(pathname, `${JSON.stringify(value, null, 2)}\n`);
945
999
  }
946
1000
 
1001
+ function writeJsonFileAtomic(pathname, value, mode = 0o600) {
1002
+ fs.mkdirSync(path.dirname(pathname), { recursive: true });
1003
+ const tempPath = `${pathname}.tmp-${process.pid}-${Date.now()}`;
1004
+ try {
1005
+ fs.writeFileSync(tempPath, `${JSON.stringify(value, null, 2)}\n`, { mode });
1006
+ fs.renameSync(tempPath, pathname);
1007
+ fs.chmodSync(pathname, mode);
1008
+ } finally {
1009
+ try {
1010
+ fs.rmSync(tempPath, { force: true });
1011
+ } catch {
1012
+ // ignored
1013
+ }
1014
+ }
1015
+ }
1016
+
947
1017
  function currentBootKey(env = process.env) {
948
1018
  const currentRoot = resolvedCurrentRuntimeRoot(env);
949
1019
  if (!currentRoot) return "";
@@ -1301,6 +1371,16 @@ function runDoctor(args = []) {
1301
1371
  fix: rsync.in_sync === false ? "npm run release:local" : "",
1302
1372
  });
1303
1373
 
1374
+ const integrationSync = integrationSyncStatus(env);
1375
+ checks.push({
1376
+ name: "framework_integrations_in_sync",
1377
+ ok: true,
1378
+ in_sync: integrationSync.in_sync,
1379
+ integrations: integrationSync.integrations,
1380
+ error: "",
1381
+ fix: integrationSync.in_sync ? "" : "wallet update --yes",
1382
+ });
1383
+
1304
1384
  const ok = checks.every((c) => c.ok);
1305
1385
  console.log(
1306
1386
  JSON.stringify(
@@ -1336,6 +1416,7 @@ function runStatus(args = []) {
1336
1416
  failed_releases: listFailedReleases(),
1337
1417
  update_available: computeUpdateAvailability(),
1338
1418
  runtime_in_sync: computeRuntimeInSync(),
1419
+ framework_integrations: integrationSyncStatus(),
1339
1420
  };
1340
1421
  if (hasFlag(args, "--verbose")) {
1341
1422
  payload.verbose = true;
@@ -1562,7 +1643,20 @@ function runInstall(args, { commandName = "install" } = {}) {
1562
1643
  switchSymlink(currentPath, releaseRoot);
1563
1644
  writeUpdateJournal("committed", { release_root: releaseRoot, previous_runtime: previousTarget }, env);
1564
1645
 
1646
+ recordManagedIntegration(
1647
+ "openclaw",
1648
+ {
1649
+ config_path: path.resolve(
1650
+ expandHome(parseFlagValue(args, "--config-path") || path.join(resolveOpenclawHome(env), "openclaw.json")),
1651
+ ),
1652
+ extension_path: path.join(currentPath, ".openclaw", "extensions", "agent-wallet"),
1653
+ package_root: path.join(currentPath, "agent-wallet"),
1654
+ },
1655
+ env,
1656
+ );
1657
+
1565
1658
  const integrationRefresh = repairInstalledEditorIntegrations(env);
1659
+ const globalCliRefresh = refreshGlobalCliIfNeeded(env);
1566
1660
 
1567
1661
  const pythonInfo = activePythonRuntimeInfo(env);
1568
1662
  const nodeInfo = activeNodeRuntimeInfo(env)
@@ -1586,6 +1680,7 @@ function runInstall(args, { commandName = "install" } = {}) {
1586
1680
  staged: Boolean(stagingRoot),
1587
1681
  release_state: "verified",
1588
1682
  integration_refresh: integrationRefresh,
1683
+ global_cli_refresh: globalCliRefresh,
1589
1684
  },
1590
1685
  null,
1591
1686
  2,
@@ -2001,6 +2096,14 @@ function runHermesInstall(args) {
2001
2096
  }
2002
2097
  }
2003
2098
 
2099
+ recordManagedIntegration("hermes", {
2100
+ hermes_home: hermesHome,
2101
+ plugin_target: pluginTarget,
2102
+ env_path: hermesEnvPath,
2103
+ restart_required: true,
2104
+ ...(enable.skipped ? {} : { registration_ok: enable.ok }),
2105
+ });
2106
+
2004
2107
  console.log(
2005
2108
  JSON.stringify(
2006
2109
  {
@@ -2086,6 +2189,15 @@ function runCodexInstall(args) {
2086
2189
  }
2087
2190
  }
2088
2191
 
2192
+ recordManagedIntegration("codex", {
2193
+ codex_home: codexHome,
2194
+ plugin_target: pluginTarget,
2195
+ marketplace_path: marketplace.marketplace_path,
2196
+ marketplace_name: marketplace.marketplace_name,
2197
+ restart_required: true,
2198
+ ...(add.skipped ? {} : { registration_ok: add.ok }),
2199
+ });
2200
+
2089
2201
  console.log(
2090
2202
  JSON.stringify(
2091
2203
  {
@@ -2281,6 +2393,16 @@ function runClaudeCodeInstall(args) {
2281
2393
  }
2282
2394
  }
2283
2395
 
2396
+ recordManagedIntegration("claude-code", {
2397
+ marketplace_dir: marketplaceDir,
2398
+ plugin_target: pluginLink,
2399
+ cache_root: path.resolve(
2400
+ expandHome(process.env.AGENT_WALLET_CLAUDE_CODE_CACHE_ROOT || "~/.claude/plugins/cache"),
2401
+ ),
2402
+ restart_required: true,
2403
+ ...(enable.skipped ? {} : { registration_ok: enable.ok }),
2404
+ });
2405
+
2284
2406
  const ok = enable.skipped || enable.ok;
2285
2407
  const pinnedCache = pinClaudeCacheCopies();
2286
2408
  const pluginDirFlagFull = `claude --plugin-dir ${pluginSource}`;
@@ -2328,7 +2450,7 @@ function pathEntryExists(pathname) {
2328
2450
  }
2329
2451
  }
2330
2452
 
2331
- function repairRuntimeSymlink(name, linkPath, desiredTarget, env = process.env) {
2453
+ function repairRuntimeSymlink(name, linkPath, desiredTarget, env = process.env, { allowExternal = false } = {}) {
2332
2454
  let rawTarget;
2333
2455
  try {
2334
2456
  const stat = fs.lstatSync(linkPath);
@@ -2348,7 +2470,7 @@ function repairRuntimeSymlink(name, linkPath, desiredTarget, env = process.env)
2348
2470
  if (absoluteTarget === path.resolve(desiredTarget) || absoluteTarget.startsWith(`${logicalCurrent}${path.sep}`)) {
2349
2471
  return { name, attempted: true, ok: true, repaired: false, reason: "already current" };
2350
2472
  }
2351
- if (!runtimeReleasePath(absoluteTarget, env)) {
2473
+ if (!allowExternal && !runtimeReleasePath(absoluteTarget, env)) {
2352
2474
  return { name, attempted: false, ok: true, repaired: false, reason: "external target preserved" };
2353
2475
  }
2354
2476
  if (!fs.existsSync(desiredTarget)) {
@@ -2358,8 +2480,7 @@ function repairRuntimeSymlink(name, linkPath, desiredTarget, env = process.env)
2358
2480
  return { name, attempted: true, ok: true, repaired: true, target: desiredTarget };
2359
2481
  }
2360
2482
 
2361
- function repairHermesEnv(env = process.env) {
2362
- const envPath = path.join(resolveHermesHome(env), ".env");
2483
+ function repairHermesEnv(envPath, env = process.env) {
2363
2484
  const existing = readEnvFile(envPath);
2364
2485
  const repaired = [];
2365
2486
  const currentPackage = path.join(currentRuntimePath(env), "agent-wallet");
@@ -2379,44 +2500,378 @@ function repairHermesEnv(env = process.env) {
2379
2500
  return repaired;
2380
2501
  }
2381
2502
 
2503
+ function legacyHermesIntegration(env = process.env) {
2504
+ const hermesHome = resolveHermesHome(env);
2505
+ const pluginTarget = path.join(hermesHome, "plugins", "agent_wallet");
2506
+ let target;
2507
+ try {
2508
+ if (!fs.lstatSync(pluginTarget).isSymbolicLink()) return null;
2509
+ target = path.resolve(path.dirname(pluginTarget), fs.readlinkSync(pluginTarget));
2510
+ } catch {
2511
+ return null;
2512
+ }
2513
+ const manifest = readTextIfExists(path.join(target, "plugin.yaml"));
2514
+ if (!/^name:\s*agent[-_]wallet\s*$/m.test(manifest)) return null;
2515
+ return recordManagedIntegration(
2516
+ "hermes",
2517
+ {
2518
+ hermes_home: hermesHome,
2519
+ plugin_target: pluginTarget,
2520
+ env_path: path.join(hermesHome, ".env"),
2521
+ adopted_legacy_install: true,
2522
+ },
2523
+ env,
2524
+ );
2525
+ }
2526
+
2527
+ function repairOpenclawIntegration(env = process.env) {
2528
+ const entry = managedIntegration("openclaw", env);
2529
+ if (!entry) {
2530
+ return { name: "openclaw", attempted: false, ok: true, repaired: false, reason: "not managed" };
2531
+ }
2532
+ const configPath = path.resolve(
2533
+ expandHome(entry.config_path || path.join(resolveOpenclawHome(env), "openclaw.json")),
2534
+ );
2535
+ let config;
2536
+ try {
2537
+ config = readJsonFile(configPath);
2538
+ } catch (error) {
2539
+ return { name: "openclaw", attempted: true, ok: false, repaired: false, error: error.message };
2540
+ }
2541
+ if (!config || typeof config !== "object") {
2542
+ return { name: "openclaw", attempted: true, ok: false, repaired: false, error: `missing ${configPath}` };
2543
+ }
2544
+
2545
+ const currentRoot = currentRuntimePath(env);
2546
+ const extensionPath = path.join(currentRoot, ".openclaw", "extensions", "agent-wallet");
2547
+ const packageRootPath = path.join(currentRoot, "agent-wallet");
2548
+ const pythonBin = resolveVenvPython(currentRoot);
2549
+ const plugins = config.plugins && typeof config.plugins === "object" ? config.plugins : (config.plugins = {});
2550
+ const load = plugins.load && typeof plugins.load === "object" ? plugins.load : (plugins.load = {});
2551
+ const paths = Array.isArray(load.paths) ? load.paths : [];
2552
+ load.paths = [
2553
+ ...paths.filter((item) => {
2554
+ const value = String(item || "");
2555
+ return !value.replaceAll("\\", "/").endsWith("/.openclaw/extensions/agent-wallet");
2556
+ }),
2557
+ extensionPath,
2558
+ ];
2559
+ const entries = plugins.entries && typeof plugins.entries === "object" ? plugins.entries : (plugins.entries = {});
2560
+ const walletEntry = entries["agent-wallet"];
2561
+ if (!walletEntry || typeof walletEntry !== "object") {
2562
+ return {
2563
+ name: "openclaw",
2564
+ attempted: false,
2565
+ ok: true,
2566
+ repaired: false,
2567
+ reason: "plugin entry not configured",
2568
+ };
2569
+ }
2570
+ walletEntry.enabled = true;
2571
+ walletEntry.config = walletEntry.config && typeof walletEntry.config === "object" ? walletEntry.config : {};
2572
+ walletEntry.config.packageRoot = packageRootPath;
2573
+ if (pythonBin) walletEntry.config.pythonBin = pythonBin;
2574
+ writeJsonFileAtomic(configPath, config);
2575
+ recordManagedIntegration(
2576
+ "openclaw",
2577
+ {
2578
+ config_path: configPath,
2579
+ extension_path: extensionPath,
2580
+ package_root: packageRootPath,
2581
+ restart_required: true,
2582
+ },
2583
+ env,
2584
+ );
2585
+ return {
2586
+ name: "openclaw",
2587
+ attempted: true,
2588
+ ok: true,
2589
+ repaired: true,
2590
+ config_path: configPath,
2591
+ restart_required: true,
2592
+ };
2593
+ }
2594
+
2595
+ function symlinkManifestMatches(linkPath, manifestRelativePath, expectedName) {
2596
+ let target;
2597
+ try {
2598
+ if (!fs.lstatSync(linkPath).isSymbolicLink()) return false;
2599
+ target = path.resolve(path.dirname(linkPath), fs.readlinkSync(linkPath));
2600
+ } catch {
2601
+ return false;
2602
+ }
2603
+ try {
2604
+ const manifest = readJsonFile(path.join(target, manifestRelativePath));
2605
+ return manifest && manifest.name === expectedName;
2606
+ } catch {
2607
+ return false;
2608
+ }
2609
+ }
2610
+
2611
+ function legacyCodexIntegration(env = process.env) {
2612
+ const marketplacePath = resolveCodexMarketplacePath(env);
2613
+ let marketplace;
2614
+ try {
2615
+ marketplace = readJsonFile(marketplacePath);
2616
+ } catch {
2617
+ return null;
2618
+ }
2619
+ const pluginTarget = path.join(resolveCodexPluginInstallRoot(env), "agent-wallet");
2620
+ const registered = Array.isArray(marketplace?.plugins) && marketplace.plugins.some(
2621
+ (item) => item?.name === "agent-wallet" && item?.source?.source === "local",
2622
+ );
2623
+ if (!registered || !symlinkManifestMatches(pluginTarget, ".codex-plugin/plugin.json", "agent-wallet")) {
2624
+ return null;
2625
+ }
2626
+ return recordManagedIntegration(
2627
+ "codex",
2628
+ {
2629
+ codex_home: resolveCodexHome(env),
2630
+ plugin_target: pluginTarget,
2631
+ marketplace_path: marketplacePath,
2632
+ marketplace_name: String(marketplace.name || "local"),
2633
+ adopted_legacy_install: true,
2634
+ },
2635
+ env,
2636
+ );
2637
+ }
2638
+
2639
+ function legacyClaudeCodeIntegration(env = process.env) {
2640
+ const marketplaceDir = resolveClaudeCodeMarketplaceDir(env);
2641
+ let manifest;
2642
+ try {
2643
+ manifest = readJsonFile(path.join(marketplaceDir, ".claude-plugin", "marketplace.json"));
2644
+ } catch {
2645
+ return null;
2646
+ }
2647
+ const pluginTarget = path.join(marketplaceDir, "plugins", "agent-wallet");
2648
+ const registered = manifest?.name === CLAUDE_CODE_MARKETPLACE_NAME &&
2649
+ Array.isArray(manifest.plugins) && manifest.plugins.some((item) => item?.name === "agent-wallet");
2650
+ if (!registered || !symlinkManifestMatches(pluginTarget, ".claude-plugin/plugin.json", "agent-wallet")) {
2651
+ return null;
2652
+ }
2653
+ return recordManagedIntegration(
2654
+ "claude-code",
2655
+ {
2656
+ marketplace_dir: marketplaceDir,
2657
+ plugin_target: pluginTarget,
2658
+ cache_root: path.resolve(
2659
+ expandHome(env.AGENT_WALLET_CLAUDE_CODE_CACHE_ROOT || "~/.claude/plugins/cache"),
2660
+ ),
2661
+ adopted_legacy_install: true,
2662
+ },
2663
+ env,
2664
+ );
2665
+ }
2666
+
2667
+ function runHostRefresh(command, args, env = process.env) {
2668
+ const binary = commandPath(command);
2669
+ if (!binary) {
2670
+ return {
2671
+ attempted: false,
2672
+ ok: false,
2673
+ error: `${command} CLI not found`,
2674
+ fix: args.join(" "),
2675
+ };
2676
+ }
2677
+ const result = spawnSync(binary, args, { cwd: packageRoot, encoding: "utf8", env });
2678
+ return {
2679
+ attempted: true,
2680
+ ok: result.status === 0,
2681
+ error: result.status === 0 ? "" : (result.stderr || result.stdout || "").trim(),
2682
+ fix: result.status === 0 ? "" : `${command} ${args.join(" ")}`,
2683
+ };
2684
+ }
2685
+
2686
+ function globalNpmPackageInfo(env = process.env) {
2687
+ const npmBin = commandPath("npm");
2688
+ if (!npmBin) return null;
2689
+ const rootResult = spawnSync(npmBin, ["root", "--global"], { encoding: "utf8", env });
2690
+ if (rootResult.status !== 0) return null;
2691
+ const packageRoot = path.join(rootResult.stdout.trim(), ...packageJson.name.split("/"));
2692
+ try {
2693
+ const manifest = readJsonFile(path.join(packageRoot, "package.json"));
2694
+ if (manifest?.name !== packageJson.name) return null;
2695
+ return { npm_bin: npmBin, package_root: packageRoot, version: manifest.version || null };
2696
+ } catch {
2697
+ return null;
2698
+ }
2699
+ }
2700
+
2701
+ function refreshGlobalCliIfNeeded(env = process.env) {
2702
+ const installed = globalNpmPackageInfo(env);
2703
+ if (!installed) {
2704
+ return { attempted: false, ok: true, reason: "global package is not installed" };
2705
+ }
2706
+ if (installed.version === packageVersion) {
2707
+ return { attempted: false, ok: true, reason: "already current", version: packageVersion };
2708
+ }
2709
+ const fromNpmCache = path.resolve(packageRoot).split(path.sep).includes("_npx");
2710
+ const forced = env.AGENT_WALLET_FORCE_GLOBAL_CLI_REFRESH === "1";
2711
+ if (!fromNpmCache && !forced) {
2712
+ return {
2713
+ attempted: false,
2714
+ ok: false,
2715
+ reason: "installer is not running from npm exec",
2716
+ installed_version: installed.version,
2717
+ target_version: packageVersion,
2718
+ fix: `npm install --global ${packageJson.name}@${packageVersion}`,
2719
+ };
2720
+ }
2721
+ const packageSpec = `${packageJson.name}@${packageVersion}`;
2722
+ const result = spawnSync(
2723
+ installed.npm_bin,
2724
+ ["install", "--global", "--no-audit", "--no-fund", packageSpec],
2725
+ { encoding: "utf8", env },
2726
+ );
2727
+ return {
2728
+ attempted: true,
2729
+ ok: result.status === 0,
2730
+ previous_version: installed.version,
2731
+ target_version: packageVersion,
2732
+ error: result.status === 0 ? "" : (result.stderr || result.stdout || "").trim(),
2733
+ fix: result.status === 0 ? "" : `npm install --global ${packageSpec}`,
2734
+ };
2735
+ }
2736
+
2737
+ function refreshCodexIntegration(entry, env = process.env) {
2738
+ const pluginTarget = path.resolve(
2739
+ expandHome(entry.plugin_target || path.join(resolveCodexPluginInstallRoot(env), "agent-wallet")),
2740
+ );
2741
+ const marketplacePath = path.resolve(
2742
+ expandHome(entry.marketplace_path || resolveCodexMarketplacePath(env)),
2743
+ );
2744
+ const link = repairRuntimeSymlink(
2745
+ "codex",
2746
+ pluginTarget,
2747
+ path.join(currentRuntimePath(env), "codex", "plugins", "agent-wallet"),
2748
+ env,
2749
+ { allowExternal: true },
2750
+ );
2751
+ if (!link.ok) return link;
2752
+ const marketplace = ensureCodexMarketplaceEntry({ marketplacePath, pluginName: "agent-wallet" });
2753
+ const registration = runHostRefresh(
2754
+ "codex",
2755
+ ["plugin", "add", `agent-wallet@${marketplace.marketplace_name}`],
2756
+ { ...env, CODEX_HOME: entry.codex_home || resolveCodexHome(env) },
2757
+ );
2758
+ recordManagedIntegration(
2759
+ "codex",
2760
+ {
2761
+ ...entry,
2762
+ plugin_target: pluginTarget,
2763
+ marketplace_path: marketplacePath,
2764
+ marketplace_name: marketplace.marketplace_name,
2765
+ registration_ok: registration.ok,
2766
+ restart_required: true,
2767
+ },
2768
+ env,
2769
+ );
2770
+ return {
2771
+ ...link,
2772
+ ok: link.ok && registration.ok,
2773
+ registration,
2774
+ restart_required: true,
2775
+ };
2776
+ }
2777
+
2778
+ function refreshClaudeCodeIntegration(entry, env = process.env) {
2779
+ const marketplaceDir = path.resolve(
2780
+ expandHome(entry.marketplace_dir || resolveClaudeCodeMarketplaceDir(env)),
2781
+ );
2782
+ const cacheRoot = path.resolve(
2783
+ expandHome(entry.cache_root || env.AGENT_WALLET_CLAUDE_CODE_CACHE_ROOT || "~/.claude/plugins/cache"),
2784
+ );
2785
+ const pluginTarget = path.resolve(
2786
+ expandHome(entry.plugin_target || path.join(marketplaceDir, "plugins", "agent-wallet")),
2787
+ );
2788
+ const link = repairRuntimeSymlink(
2789
+ "claude-code",
2790
+ pluginTarget,
2791
+ path.join(currentRuntimePath(env), "claude-code", "plugins", "agent-wallet"),
2792
+ env,
2793
+ { allowExternal: true },
2794
+ );
2795
+ if (!link.ok) return link;
2796
+ ensureClaudeCodeMarketplace(
2797
+ marketplaceDir,
2798
+ path.join(currentRuntimePath(env), "claude-code", "plugins", "agent-wallet"),
2799
+ true,
2800
+ );
2801
+ const marketplaceAdd = runHostRefresh(
2802
+ "claude",
2803
+ ["plugin", "marketplace", "add", marketplaceDir, "--scope", "user"],
2804
+ env,
2805
+ );
2806
+ const registration = marketplaceAdd.ok
2807
+ ? runHostRefresh(
2808
+ "claude",
2809
+ ["plugin", "install", `agent-wallet@${CLAUDE_CODE_MARKETPLACE_NAME}`, "--scope", "user"],
2810
+ env,
2811
+ )
2812
+ : { attempted: false, ok: false, error: "marketplace refresh failed", fix: marketplaceAdd.fix };
2813
+ const cachePins = pinClaudeCacheCopies({
2814
+ ...env,
2815
+ AGENT_WALLET_CLAUDE_CODE_CACHE_ROOT: cacheRoot,
2816
+ });
2817
+ recordManagedIntegration(
2818
+ "claude-code",
2819
+ {
2820
+ ...entry,
2821
+ marketplace_dir: marketplaceDir,
2822
+ plugin_target: pluginTarget,
2823
+ cache_root: cacheRoot,
2824
+ registration_ok: registration.ok,
2825
+ restart_required: true,
2826
+ },
2827
+ env,
2828
+ );
2829
+ return {
2830
+ ...link,
2831
+ ok: link.ok && marketplaceAdd.ok && registration.ok,
2832
+ marketplace_add: marketplaceAdd,
2833
+ registration,
2834
+ cache_pins: cachePins,
2835
+ restart_required: true,
2836
+ };
2837
+ }
2838
+
2382
2839
  function repairInstalledEditorIntegrations(env = process.env) {
2383
- const results = [];
2840
+ const results = [repairOpenclawIntegration(env)];
2384
2841
  const currentRoot = currentRuntimePath(env);
2385
- const hermesTarget = path.join(resolveHermesHome(env), "plugins", "agent_wallet");
2386
- if (pathEntryExists(hermesTarget) || fs.existsSync(path.join(resolveHermesHome(env), ".env"))) {
2842
+ const hermesEntry = managedIntegration("hermes", env) || legacyHermesIntegration(env);
2843
+ if (hermesEntry) {
2844
+ const hermesTarget = path.resolve(expandHome(hermesEntry.plugin_target));
2845
+ const hermesEnvPath = path.resolve(expandHome(hermesEntry.env_path));
2387
2846
  const result = repairRuntimeSymlink(
2388
2847
  "hermes",
2389
2848
  hermesTarget,
2390
2849
  path.join(currentRoot, "hermes", "plugins", "agent_wallet"),
2391
2850
  env,
2851
+ { allowExternal: true },
2392
2852
  );
2393
- result.env_repaired = repairHermesEnv(env);
2853
+ result.env_repaired = repairHermesEnv(hermesEnvPath, env);
2854
+ result.restart_required = true;
2855
+ if (result.ok) {
2856
+ recordManagedIntegration(
2857
+ "hermes",
2858
+ {
2859
+ ...hermesEntry,
2860
+ plugin_target: hermesTarget,
2861
+ env_path: hermesEnvPath,
2862
+ restart_required: true,
2863
+ },
2864
+ env,
2865
+ );
2866
+ }
2394
2867
  results.push(result);
2395
2868
  }
2396
2869
 
2397
- const codexTarget = path.join(resolveCodexPluginInstallRoot(env), "agent-wallet");
2398
- if (pathEntryExists(codexTarget)) {
2399
- results.push(
2400
- repairRuntimeSymlink(
2401
- "codex",
2402
- codexTarget,
2403
- path.join(currentRoot, "codex", "plugins", "agent-wallet"),
2404
- env,
2405
- ),
2406
- );
2407
- }
2870
+ const codexEntry = managedIntegration("codex", env) || legacyCodexIntegration(env);
2871
+ if (codexEntry) results.push(refreshCodexIntegration(codexEntry, env));
2408
2872
 
2409
- const claudeTarget = path.join(resolveClaudeCodeMarketplaceDir(env), "plugins", "agent-wallet");
2410
- if (pathEntryExists(claudeTarget)) {
2411
- const result = repairRuntimeSymlink(
2412
- "claude-code",
2413
- claudeTarget,
2414
- path.join(currentRoot, "claude-code", "plugins", "agent-wallet"),
2415
- env,
2416
- );
2417
- result.cache_pins = pinClaudeCacheCopies(env);
2418
- results.push(result);
2419
- }
2873
+ const claudeEntry = managedIntegration("claude-code", env) || legacyClaudeCodeIntegration(env);
2874
+ if (claudeEntry) results.push(refreshClaudeCodeIntegration(claudeEntry, env));
2420
2875
  return results;
2421
2876
  }
2422
2877
 
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "agent-wallet",
3
3
  "displayName": "Agent Wallet",
4
- "version": "0.1.74",
4
+ "version": "0.1.75",
5
5
  "description": "Claude Code bridge for the existing AgentLayer wallet runtime. Connects to Solana, Bitcoin, and EVM wallets without creating a new one.",
6
6
  "author": {
7
7
  "name": "AgentLayer"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-wallet",
3
- "version": "0.1.74",
3
+ "version": "0.1.75",
4
4
  "description": "Codex plugin bridge for the AgentLayer wallet runtime.",
5
5
  "author": {
6
6
  "name": "AgentLayer"
@@ -1,5 +1,5 @@
1
1
  name: agent-wallet
2
- version: 0.1.74
2
+ version: 0.1.75
3
3
  description: Thin Hermes Agent bridge to the existing AgentLayer/OpenClaw wallet backend
4
4
  provides_tools:
5
5
  - agent_wallet_tools
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentlayer.tech/wallet",
3
- "version": "0.1.74",
3
+ "version": "0.1.75",
4
4
  "description": "NPM installer for the OpenClaw Agent Wallet local runtime.",
5
5
  "type": "module",
6
6
  "repository": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wdk-btc-wallet",
3
- "version": "0.1.74",
3
+ "version": "0.1.75",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "description": "Separate BTC-only wallet service built on Tether WDK.",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wdk-evm-wallet",
3
- "version": "0.1.74",
3
+ "version": "0.1.75",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "description": "Separate EVM wallet service built on Tether WDK.",