@agentlayer.tech/wallet 0.1.13 → 0.1.15

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.
@@ -0,0 +1,196 @@
1
+ import {
2
+ executePayApiRequest,
3
+ getPayServiceEndpoints,
4
+ getPayStatus,
5
+ getPayWalletInfo,
6
+ searchPayServices,
7
+ } from "./core.mjs";
8
+
9
+ const PLUGIN_ID = "pay-bridge";
10
+
11
+ function asContent(data) {
12
+ return {
13
+ content: [
14
+ {
15
+ type: "text",
16
+ text: JSON.stringify(data, null, 2),
17
+ },
18
+ ],
19
+ };
20
+ }
21
+
22
+ function resolvePluginConfig(api) {
23
+ const globalConfig = api?.config ?? {};
24
+ const pluginEntry = globalConfig?.plugins?.entries?.[PLUGIN_ID];
25
+ return pluginEntry?.config ?? globalConfig?.config ?? {};
26
+ }
27
+
28
+ function registerTool(api, definition) {
29
+ api.registerTool({
30
+ name: definition.name,
31
+ description: definition.description,
32
+ parameters: definition.parameters,
33
+ returns: {
34
+ type: "object",
35
+ additionalProperties: true,
36
+ },
37
+ async execute(_id, params = {}) {
38
+ const config = resolvePluginConfig(api);
39
+ let result;
40
+ if (definition.name === "pay_status") {
41
+ result = await getPayStatus(config, { cwd: process.cwd() });
42
+ } else if (definition.name === "pay_wallet_info") {
43
+ result = await getPayWalletInfo(config, { cwd: process.cwd() });
44
+ } else if (definition.name === "pay_search_services") {
45
+ result = await searchPayServices(config, params, { cwd: process.cwd() });
46
+ } else if (definition.name === "pay_get_service_endpoints") {
47
+ result = await getPayServiceEndpoints(config, params, { cwd: process.cwd() });
48
+ } else if (definition.name === "pay_api_request") {
49
+ result = await executePayApiRequest(config, params, { cwd: process.cwd() });
50
+ } else {
51
+ throw new Error(`Unsupported pay-bridge tool: ${definition.name}`);
52
+ }
53
+ return asContent(result);
54
+ },
55
+ });
56
+ }
57
+
58
+ const toolDefinitions = [
59
+ {
60
+ name: "pay_status",
61
+ description:
62
+ "Check whether the local pay.sh CLI is installed and whether a pay wallet/account is configured. Use this before any paid API workflow.",
63
+ parameters: {
64
+ type: "object",
65
+ properties: {},
66
+ additionalProperties: false,
67
+ },
68
+ },
69
+ {
70
+ name: "pay_wallet_info",
71
+ description:
72
+ "Show pay wallet/account status. This wallet is separate from the AgentLayer execution wallet and is only for pay.sh API payments.",
73
+ parameters: {
74
+ type: "object",
75
+ properties: {},
76
+ additionalProperties: false,
77
+ },
78
+ },
79
+ {
80
+ name: "pay_search_services",
81
+ description:
82
+ "Search the pay.sh skills catalog for paid APIs. Prefer this instead of guessing URLs manually.",
83
+ parameters: {
84
+ type: "object",
85
+ properties: {
86
+ query: {
87
+ type: "string",
88
+ description: "Search text for service names, descriptions, or endpoint paths.",
89
+ },
90
+ category: {
91
+ type: "string",
92
+ description: "Optional category filter such as ai_ml, maps, data, compute, search, crypto_finance.",
93
+ },
94
+ account: {
95
+ type: "string",
96
+ description: "Optional pay account override.",
97
+ },
98
+ },
99
+ additionalProperties: false,
100
+ },
101
+ },
102
+ {
103
+ name: "pay_get_service_endpoints",
104
+ description:
105
+ "List the discoverable endpoints for a pay.sh service/resource pair and return their gateway URLs. Use the returned URL with pay_api_request.",
106
+ parameters: {
107
+ type: "object",
108
+ properties: {
109
+ service_fqn: {
110
+ type: "string",
111
+ description: "Fully qualified pay service name, for example solana-foundation/google/language.",
112
+ },
113
+ resource: {
114
+ type: "string",
115
+ description: "Resource name inside the service, for example entities or jobs.",
116
+ },
117
+ account: {
118
+ type: "string",
119
+ description: "Optional pay account override.",
120
+ },
121
+ },
122
+ required: ["service_fqn", "resource"],
123
+ additionalProperties: false,
124
+ },
125
+ },
126
+ {
127
+ name: "pay_api_request",
128
+ description:
129
+ "Call a paid API through the local pay.sh CLI using a URL returned by pay_get_service_endpoints. Requires explicit user_confirmed=true and keeps the pay wallet separate from AgentLayer execution wallets.",
130
+ optional: true,
131
+ parameters: {
132
+ type: "object",
133
+ properties: {
134
+ service_fqn: {
135
+ type: "string",
136
+ description: "Fully qualified pay service name used to validate the request URL.",
137
+ },
138
+ resource: {
139
+ type: "string",
140
+ description: "Resource name used to validate the request URL.",
141
+ },
142
+ url: {
143
+ type: "string",
144
+ description: "Exact HTTPS gateway URL returned by pay_get_service_endpoints.",
145
+ },
146
+ method: {
147
+ type: "string",
148
+ description: "HTTP method such as GET or POST.",
149
+ },
150
+ headers: {
151
+ type: "object",
152
+ additionalProperties: { type: "string" },
153
+ description: "Optional HTTP headers.",
154
+ },
155
+ query: {
156
+ type: "object",
157
+ additionalProperties: true,
158
+ description: "Optional query parameters to append to the URL.",
159
+ },
160
+ json_body: {
161
+ description: "Optional JSON request body.",
162
+ },
163
+ text_body: {
164
+ type: "string",
165
+ description: "Optional raw text request body. Do not provide with json_body.",
166
+ },
167
+ account: {
168
+ type: "string",
169
+ description: "Optional pay account override.",
170
+ },
171
+ parse_json_response: {
172
+ type: "boolean",
173
+ description: "If true, attempt to parse the response body as JSON.",
174
+ },
175
+ purpose: {
176
+ type: "string",
177
+ description: "Short user-facing reason for this paid API call.",
178
+ },
179
+ user_confirmed: {
180
+ type: "boolean",
181
+ description: "Must be true for paid API requests.",
182
+ },
183
+ },
184
+ required: ["service_fqn", "resource", "url", "method", "purpose", "user_confirmed"],
185
+ additionalProperties: false,
186
+ },
187
+ },
188
+ ];
189
+
190
+ export default function registerPayBridgePlugin(api) {
191
+ api?.logger?.info?.("[pay-bridge] registering pay.sh OpenClaw plugin");
192
+ for (const definition of toolDefinitions) {
193
+ registerTool(api, definition);
194
+ }
195
+ api?.logger?.info?.(`[pay-bridge] registered ${toolDefinitions.length} pay tools`);
196
+ }
@@ -0,0 +1,196 @@
1
+ import {
2
+ executePayApiRequest,
3
+ getPayServiceEndpoints,
4
+ getPayStatus,
5
+ getPayWalletInfo,
6
+ searchPayServices,
7
+ } from "./core.mjs";
8
+
9
+ const PLUGIN_ID = "pay-bridge";
10
+
11
+ function asContent(data) {
12
+ return {
13
+ content: [
14
+ {
15
+ type: "text",
16
+ text: JSON.stringify(data, null, 2),
17
+ },
18
+ ],
19
+ };
20
+ }
21
+
22
+ function resolvePluginConfig(api) {
23
+ const globalConfig = api?.config ?? {};
24
+ const pluginEntry = globalConfig?.plugins?.entries?.[PLUGIN_ID];
25
+ return pluginEntry?.config ?? globalConfig?.config ?? {};
26
+ }
27
+
28
+ function registerTool(api, definition) {
29
+ api.registerTool({
30
+ name: definition.name,
31
+ description: definition.description,
32
+ parameters: definition.parameters,
33
+ returns: {
34
+ type: "object",
35
+ additionalProperties: true,
36
+ },
37
+ async execute(_id, params = {}) {
38
+ const config = resolvePluginConfig(api);
39
+ let result;
40
+ if (definition.name === "pay_status") {
41
+ result = await getPayStatus(config, { cwd: process.cwd() });
42
+ } else if (definition.name === "pay_wallet_info") {
43
+ result = await getPayWalletInfo(config, { cwd: process.cwd() });
44
+ } else if (definition.name === "pay_search_services") {
45
+ result = await searchPayServices(config, params, { cwd: process.cwd() });
46
+ } else if (definition.name === "pay_get_service_endpoints") {
47
+ result = await getPayServiceEndpoints(config, params, { cwd: process.cwd() });
48
+ } else if (definition.name === "pay_api_request") {
49
+ result = await executePayApiRequest(config, params, { cwd: process.cwd() });
50
+ } else {
51
+ throw new Error(`Unsupported pay-bridge tool: ${definition.name}`);
52
+ }
53
+ return asContent(result);
54
+ },
55
+ });
56
+ }
57
+
58
+ const toolDefinitions = [
59
+ {
60
+ name: "pay_status",
61
+ description:
62
+ "Check whether the local pay.sh CLI is installed and whether a pay wallet/account is configured. Use this before any paid API workflow.",
63
+ parameters: {
64
+ type: "object",
65
+ properties: {},
66
+ additionalProperties: false,
67
+ },
68
+ },
69
+ {
70
+ name: "pay_wallet_info",
71
+ description:
72
+ "Show pay wallet/account status. This wallet is separate from the AgentLayer execution wallet and is only for pay.sh API payments.",
73
+ parameters: {
74
+ type: "object",
75
+ properties: {},
76
+ additionalProperties: false,
77
+ },
78
+ },
79
+ {
80
+ name: "pay_search_services",
81
+ description:
82
+ "Search the pay.sh skills catalog for paid APIs. Prefer this instead of guessing URLs manually.",
83
+ parameters: {
84
+ type: "object",
85
+ properties: {
86
+ query: {
87
+ type: "string",
88
+ description: "Search text for service names, descriptions, or endpoint paths.",
89
+ },
90
+ category: {
91
+ type: "string",
92
+ description: "Optional category filter such as ai_ml, maps, data, compute, search, crypto_finance.",
93
+ },
94
+ account: {
95
+ type: "string",
96
+ description: "Optional pay account override.",
97
+ },
98
+ },
99
+ additionalProperties: false,
100
+ },
101
+ },
102
+ {
103
+ name: "pay_get_service_endpoints",
104
+ description:
105
+ "List the discoverable endpoints for a pay.sh service/resource pair and return their gateway URLs. Use the returned URL with pay_api_request.",
106
+ parameters: {
107
+ type: "object",
108
+ properties: {
109
+ service_fqn: {
110
+ type: "string",
111
+ description: "Fully qualified pay service name, for example solana-foundation/google/language.",
112
+ },
113
+ resource: {
114
+ type: "string",
115
+ description: "Resource name inside the service, for example entities or jobs.",
116
+ },
117
+ account: {
118
+ type: "string",
119
+ description: "Optional pay account override.",
120
+ },
121
+ },
122
+ required: ["service_fqn", "resource"],
123
+ additionalProperties: false,
124
+ },
125
+ },
126
+ {
127
+ name: "pay_api_request",
128
+ description:
129
+ "Call a paid API through the local pay.sh CLI using a URL returned by pay_get_service_endpoints. Requires explicit user_confirmed=true and keeps the pay wallet separate from AgentLayer execution wallets.",
130
+ optional: true,
131
+ parameters: {
132
+ type: "object",
133
+ properties: {
134
+ service_fqn: {
135
+ type: "string",
136
+ description: "Fully qualified pay service name used to validate the request URL.",
137
+ },
138
+ resource: {
139
+ type: "string",
140
+ description: "Resource name used to validate the request URL.",
141
+ },
142
+ url: {
143
+ type: "string",
144
+ description: "Exact HTTPS gateway URL returned by pay_get_service_endpoints.",
145
+ },
146
+ method: {
147
+ type: "string",
148
+ description: "HTTP method such as GET or POST.",
149
+ },
150
+ headers: {
151
+ type: "object",
152
+ additionalProperties: { type: "string" },
153
+ description: "Optional HTTP headers.",
154
+ },
155
+ query: {
156
+ type: "object",
157
+ additionalProperties: true,
158
+ description: "Optional query parameters to append to the URL.",
159
+ },
160
+ json_body: {
161
+ description: "Optional JSON request body.",
162
+ },
163
+ text_body: {
164
+ type: "string",
165
+ description: "Optional raw text request body. Do not provide with json_body.",
166
+ },
167
+ account: {
168
+ type: "string",
169
+ description: "Optional pay account override.",
170
+ },
171
+ parse_json_response: {
172
+ type: "boolean",
173
+ description: "If true, attempt to parse the response body as JSON.",
174
+ },
175
+ purpose: {
176
+ type: "string",
177
+ description: "Short user-facing reason for this paid API call.",
178
+ },
179
+ user_confirmed: {
180
+ type: "boolean",
181
+ description: "Must be true for paid API requests.",
182
+ },
183
+ },
184
+ required: ["service_fqn", "resource", "url", "method", "purpose", "user_confirmed"],
185
+ additionalProperties: false,
186
+ },
187
+ },
188
+ ];
189
+
190
+ export default function registerPayBridgePlugin(api) {
191
+ api?.logger?.info?.("[pay-bridge] registering pay.sh OpenClaw plugin");
192
+ for (const definition of toolDefinitions) {
193
+ registerTool(api, definition);
194
+ }
195
+ api?.logger?.info?.(`[pay-bridge] registered ${toolDefinitions.length} pay tools`);
196
+ }
@@ -0,0 +1,34 @@
1
+ {
2
+ "id": "pay-bridge",
3
+ "name": "pay.sh Bridge",
4
+ "description": "Thin OpenClaw bridge to the local pay.sh CLI for paid API discovery and execution.",
5
+ "version": "0.1.0",
6
+ "contracts": {
7
+ "tools": [
8
+ "pay_status",
9
+ "pay_wallet_info",
10
+ "pay_search_services",
11
+ "pay_get_service_endpoints",
12
+ "pay_api_request"
13
+ ]
14
+ },
15
+ "skills": ["skills/pay-operator"],
16
+ "configSchema": {
17
+ "type": "object",
18
+ "additionalProperties": false,
19
+ "properties": {
20
+ "payBinary": {
21
+ "type": "string",
22
+ "description": "Absolute path or executable name for the local pay.sh binary."
23
+ },
24
+ "defaultAccount": {
25
+ "type": "string",
26
+ "description": "Optional pay account name to use when a tool call does not specify one."
27
+ },
28
+ "requireHttps": {
29
+ "type": "boolean",
30
+ "description": "If true, pay_api_request refuses non-HTTPS URLs."
31
+ }
32
+ }
33
+ }
34
+ }
@@ -0,0 +1,49 @@
1
+ {
2
+ "name": "@agentlayertech/pay-bridge-plugin",
3
+ "version": "0.1.15",
4
+ "description": "OpenClaw plugin bridge for the local pay.sh CLI.",
5
+ "type": "module",
6
+ "license": "SEE LICENSE IN ../../../LICENSE",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/lopushok9/Agent-Layer.git",
10
+ "directory": ".openclaw/extensions/pay-bridge"
11
+ },
12
+ "bugs": {
13
+ "url": "https://github.com/lopushok9/Agent-Layer/issues"
14
+ },
15
+ "homepage": "https://github.com/lopushok9/Agent-Layer/tree/main/.openclaw/extensions/pay-bridge#readme",
16
+ "publishConfig": {
17
+ "access": "public"
18
+ },
19
+ "files": [
20
+ "index.ts",
21
+ "core.mjs",
22
+ "dist/",
23
+ "openclaw.plugin.json",
24
+ "README.md",
25
+ "skills/"
26
+ ],
27
+ "openclaw": {
28
+ "extensions": [
29
+ "./index.ts"
30
+ ],
31
+ "runtimeExtensions": [
32
+ "./dist/index.js"
33
+ ],
34
+ "compat": {
35
+ "pluginApi": ">=2026.3.24-beta.2",
36
+ "minGatewayVersion": "2026.3.24-beta.2"
37
+ },
38
+ "build": {
39
+ "openclawVersion": "2026.3.24-beta.2",
40
+ "pluginSdkVersion": "2026.3.24-beta.2"
41
+ }
42
+ },
43
+ "keywords": [
44
+ "openclaw",
45
+ "plugin",
46
+ "pay",
47
+ "payments"
48
+ ]
49
+ }
@@ -0,0 +1,20 @@
1
+ # pay-operator
2
+
3
+ Use this skill when the user wants to discover or call paid APIs through `pay`.
4
+
5
+ ## Rules
6
+
7
+ - Treat the `pay` wallet as separate from the AgentLayer execution wallet.
8
+ - Do not use `agent-wallet` tools for `pay` account management.
9
+ - Do not fall back to shell commands when the `pay-bridge` tools exist.
10
+ - Prefer this order:
11
+ 1. `pay_status`
12
+ 2. `pay_search_services`
13
+ 3. `pay_get_service_endpoints`
14
+ 4. `pay_api_request`
15
+
16
+ ## Notes
17
+
18
+ - `pay_api_request` requires `purpose` and `user_confirmed=true`.
19
+ - Use the exact gateway URL returned by `pay_get_service_endpoints`.
20
+ - If `pay_status` shows no configured account, stop and ask the user to finish `pay setup`.
@@ -0,0 +1,38 @@
1
+ import assert from "node:assert/strict";
2
+
3
+ import {
4
+ endpointPayloadContainsUrl,
5
+ parseAccountListOutput,
6
+ parseWhoamiOutput,
7
+ } from "./core.mjs";
8
+
9
+ const whoami = parseWhoamiOutput(`
10
+ yuriytsygankov
11
+ \u001b[2m(no mainnet account — run \`pay setup\`)\u001b[0m
12
+ `);
13
+ assert.equal(whoami.system_user, "yuriytsygankov");
14
+ assert.equal(whoami.has_mainnet_account, false);
15
+
16
+ const accounts = parseAccountListOutput(`
17
+ \u001b[2mNo accounts found. Run \`pay account new\` to create one.\u001b[0m
18
+ `);
19
+ assert.equal(accounts.has_accounts, false);
20
+
21
+ const endpointPayload = {
22
+ endpoints: [
23
+ {
24
+ method: "POST",
25
+ url: "https://api.example.com/v1/invoke",
26
+ },
27
+ ],
28
+ };
29
+ assert.equal(
30
+ endpointPayloadContainsUrl(endpointPayload, "https://api.example.com/v1/invoke"),
31
+ true
32
+ );
33
+ assert.equal(
34
+ endpointPayloadContainsUrl(endpointPayload, "https://api.example.com/v1/other"),
35
+ false
36
+ );
37
+
38
+ console.log("smoke_pay_bridge: ok");
package/CHANGELOG.md CHANGED
@@ -2,6 +2,35 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ - Added ClawHub-publishable OpenClaw plugin package metadata for
6
+ `.openclaw/extensions/agent-wallet` and `.openclaw/extensions/pay-bridge`,
7
+ including required `openclaw.compat`, `openclaw.build`, and
8
+ `runtimeExtensions` fields for native `openclaw plugins install clawhub:...`
9
+ installs.
10
+ - Added a reproducible OpenClaw plugin package build/check script at
11
+ `scripts/manage_openclaw_plugin_packages.mjs` to generate published runtime
12
+ JS artifacts under `.openclaw/extensions/*/dist/`.
13
+ - Updated the `agent-wallet` OpenClaw bridge to auto-check the packaged runtime
14
+ path at `~/.openclaw/agent-wallet-runtime/current/agent-wallet` before local
15
+ workspace fallbacks, so a ClawHub-installed plugin can ride on top of the
16
+ existing npm runtime installer.
17
+ - Documented the dual-install model: keep `npx @agentlayer.tech/wallet install`
18
+ for runtime/bootstrap, and use `openclaw plugins install clawhub:...` for the
19
+ native OpenClaw plugin packages.
20
+ - Added a GitHub Actions workflow at `.github/workflows/clawhub-plugins.yml`
21
+ that can dry-run ClawHub publishes on pull requests and publish both OpenClaw
22
+ plugin packages on `v*` tags or manual dispatch.
23
+
24
+ ## v0.1.14 - 2026-05-13
25
+
26
+ - Added a separate `.openclaw/extensions/pay-bridge/` plugin that keeps
27
+ `pay.sh` API payments outside the main AgentLayer execution wallet stack.
28
+ - Added OpenClaw tools for local `pay` discovery and execution:
29
+ `pay_status`, `pay_wallet_info`, `pay_search_services`,
30
+ `pay_get_service_endpoints`, and `pay_api_request`.
31
+ - Updated the local OpenClaw installer/runtime config flow to package and
32
+ enable the `pay-bridge` plugin alongside `agent-wallet`, including its
33
+ tool allowlist and absolute `pay` binary path when available.
5
34
  - Added an optional Hermes Agent bridge plugin under `hermes/plugins/agent_wallet`
6
35
  that forwards into the existing Python wallet CLI instead of duplicating
7
36
  OpenClaw wallet tools or policy.
package/README.md CHANGED
@@ -18,7 +18,7 @@ AgentLayer is a beta local-first wallet and finance stack for agents.
18
18
  The repository includes:
19
19
 
20
20
  - `agent-wallet/` - the main wallet backend for AgentLayer
21
- - `.openclaw/` - the local AgentLayer bridge layer
21
+ - `.openclaw/` - the local AgentLayer bridge layer, including the OpenClaw wallet bridge and the `pay.sh` API-payments bridge
22
22
  - `hermes/` - optional Hermes Agent plugin bridge for the same wallet backend
23
23
  - `wdk-btc-wallet/` - the local Bitcoin wallet service
24
24
  - `wdk-evm-wallet/` - the local EVM wallet service
@@ -51,6 +51,15 @@ Install through npm:
51
51
  npx @agentlayer.tech/wallet install --yes
52
52
  ```
53
53
 
54
+ Install the native OpenClaw plugins from ClawHub:
55
+
56
+ ```bash
57
+ openclaw plugins install clawhub:@agentlayertech/agent-wallet-plugin
58
+ openclaw plugins install clawhub:@agentlayertech/pay-bridge-plugin
59
+ ```
60
+
61
+ Those ClawHub packages do not replace the npm installer. Keep `npx @agentlayer.tech/wallet install --yes` for laying down the local wallet runtime, Python backend, and helper services. The ClawHub packages only install the OpenClaw plugin surfaces that point at that runtime.
62
+
54
63
  Or install the CLI globally first:
55
64
 
56
65
  ```bash
@@ -77,6 +86,29 @@ wallet update --yes
77
86
  wallet rollback
78
87
  ```
79
88
 
89
+ ## Native OpenClaw plugin installs
90
+
91
+ Use ClawHub when you want the plugin itself to be installed through OpenClaw:
92
+
93
+ ```bash
94
+ openclaw plugins install clawhub:@agentlayertech/agent-wallet-plugin
95
+ openclaw plugins install clawhub:@agentlayertech/pay-bridge-plugin
96
+ ```
97
+
98
+ Recommended order:
99
+
100
+ 1. Install or update the local runtime with `npx @agentlayer.tech/wallet install --yes`.
101
+ 2. Install the plugin package from ClawHub with `openclaw plugins install clawhub:...`.
102
+ 3. Restart the OpenClaw gateway and enable/configure the plugin entry in `openclaw.json`.
103
+
104
+ The `agent-wallet` ClawHub plugin auto-checks the standard runtime path at:
105
+
106
+ ```bash
107
+ ~/.openclaw/agent-wallet-runtime/current/agent-wallet
108
+ ```
109
+
110
+ If your runtime lives elsewhere, set `plugins.entries.agent-wallet.config.packageRoot` explicitly.
111
+
80
112
  Install from a local clone:
81
113
 
82
114
  ```bash