@nevermined-io/openclaw-plugin 1.0.11-rc.1 → 1.0.11

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.
package/README.md CHANGED
@@ -8,9 +8,23 @@ OpenClaw plugin for [Nevermined](https://nevermined.io) — exposes AI agent pay
8
8
  openclaw plugin install @nevermined-io/openclaw-plugin
9
9
  ```
10
10
 
11
- ## Configuration
11
+ ## Authentication
12
+
13
+ The plugin supports two ways to provide your Nevermined API key:
14
+
15
+ ### Option A: Browser login (recommended)
16
+
17
+ Use the `/nvm-login` command from any chat channel, or call the `nevermined.login` gateway method. This opens a browser window where you authenticate with Nevermined, and the API key is captured automatically.
18
+
19
+ ```
20
+ /nvm-login # Login to sandbox (default)
21
+ /nvm-login live # Login to live environment
22
+ /nvm-logout # Remove stored API key
23
+ ```
24
+
25
+ ### Option B: Manual configuration
12
26
 
13
- Add the Nevermined plugin config to your `openclaw.json`:
27
+ Add your API key directly to `openclaw.json`:
14
28
 
15
29
  ```json
16
30
  {
@@ -26,9 +40,11 @@ Add the Nevermined plugin config to your `openclaw.json`:
26
40
  }
27
41
  ```
28
42
 
43
+ ## Configuration
44
+
29
45
  | Field | Required | Default | Description |
30
46
  |-------|----------|---------|-------------|
31
- | `nvmApiKey` | Yes | — | Your Nevermined API key |
47
+ | `nvmApiKey` | No | — | Your Nevermined API key (or use `/nvm-login`) |
32
48
  | `environment` | No | `sandbox` | `sandbox` or `live` |
33
49
  | `planId` | No | — | Default plan ID for subscriber tools |
34
50
  | `agentId` | No | — | Default agent ID for multi-agent plans |
@@ -36,6 +52,13 @@ Add the Nevermined plugin config to your `openclaw.json`:
36
52
 
37
53
  ## Available Tools
38
54
 
55
+ ### Authentication
56
+
57
+ | Tool / Command | Description |
58
+ |----------------|-------------|
59
+ | `nevermined.login` / `/nvm-login` | Authenticate via browser login |
60
+ | `nevermined.logout` / `/nvm-logout` | Remove stored API key |
61
+
39
62
  ### Subscriber Tools
40
63
 
41
64
  | Tool | Description | Key Params |
package/dist/auth.d.ts ADDED
@@ -0,0 +1,13 @@
1
+ import type { EnvironmentName } from '@nevermined-io/payments';
2
+ export interface LoginResult {
3
+ nvmApiKey: string;
4
+ environment: string;
5
+ loginUrl: string;
6
+ }
7
+ /**
8
+ * Starts a one-shot HTTP server, opens the Nevermined login page in the browser,
9
+ * and resolves with the API key once the callback is received.
10
+ */
11
+ export declare function startLoginFlow(environment: EnvironmentName, openBrowserFn?: (url: string) => Promise<void>): Promise<LoginResult>;
12
+ export declare function openBrowser(url: string): Promise<void>;
13
+ //# sourceMappingURL=auth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAA;AAa9D,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,MAAM,CAAA;IACjB,WAAW,EAAE,MAAM,CAAA;IACnB,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED;;;GAGG;AACH,wBAAsB,cAAc,CAClC,WAAW,EAAE,eAAe,EAC5B,aAAa,GAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAe,GAC1D,OAAO,CAAC,WAAW,CAAC,CAiEtB;AAED,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAoBtD"}
package/dist/auth.js ADDED
@@ -0,0 +1,98 @@
1
+ import { createServer } from 'http';
2
+ import { execFile } from 'child_process';
3
+ import { Environments } from '@nevermined-io/payments';
4
+ const LOGIN_TIMEOUT_MS = 5 * 60 * 1000; // 5 minutes
5
+ const SUCCESS_HTML = `
6
+ <html><body style="font-family: system-ui, sans-serif; display: flex; justify-content: center; align-items: center; height: 100vh; margin: 0; background: #f8f9fa;">
7
+ <div style="text-align: center;">
8
+ <h2>Authentication successful!</h2>
9
+ <p>You can close this tab and return to your application.</p>
10
+ </div>
11
+ </body></html>
12
+ `;
13
+ /**
14
+ * Starts a one-shot HTTP server, opens the Nevermined login page in the browser,
15
+ * and resolves with the API key once the callback is received.
16
+ */
17
+ export async function startLoginFlow(environment, openBrowserFn = openBrowser) {
18
+ const envInfo = Environments[environment];
19
+ if (!envInfo?.frontend) {
20
+ throw new Error(`Unknown environment: ${environment}`);
21
+ }
22
+ const frontendUrl = envInfo.frontend;
23
+ const nvmApiKey = await new Promise((resolve, reject) => {
24
+ const server = createServer((req, res) => {
25
+ const url = new URL(req.url || '/', 'http://localhost');
26
+ if (url.pathname !== '/callback') {
27
+ res.writeHead(404);
28
+ res.end('Not found');
29
+ return;
30
+ }
31
+ const key = url.searchParams.get('nvm_api_key');
32
+ if (!key) {
33
+ res.writeHead(400);
34
+ res.end('Missing nvm_api_key parameter');
35
+ return;
36
+ }
37
+ res.writeHead(200, { 'Content-Type': 'text/html' });
38
+ res.end(SUCCESS_HTML);
39
+ clearTimeout(timeout);
40
+ server.close();
41
+ resolve(key);
42
+ });
43
+ const timeout = setTimeout(() => {
44
+ server.close();
45
+ reject(new Error('Login timed out after 5 minutes. Please try again.'));
46
+ }, LOGIN_TIMEOUT_MS);
47
+ server.listen(0, '127.0.0.1', () => {
48
+ const addr = server.address();
49
+ if (!addr || typeof addr === 'string') {
50
+ clearTimeout(timeout);
51
+ server.close();
52
+ reject(new Error('Failed to start local server'));
53
+ return;
54
+ }
55
+ const port = addr.port;
56
+ const callbackUrl = encodeURIComponent(`http://localhost:${port}/callback`);
57
+ const loginUrl = `${frontendUrl}/auth/cli?callback_url=${callbackUrl}`;
58
+ openBrowserFn(loginUrl).catch(() => {
59
+ // Browser open failed — the caller should provide the URL to the user
60
+ });
61
+ });
62
+ server.on('error', (err) => {
63
+ clearTimeout(timeout);
64
+ reject(new Error(`Failed to start local server: ${err.message}`));
65
+ });
66
+ });
67
+ return {
68
+ nvmApiKey,
69
+ environment,
70
+ loginUrl: `${frontendUrl}/auth/cli`,
71
+ };
72
+ }
73
+ export function openBrowser(url) {
74
+ return new Promise((resolve, reject) => {
75
+ const platform = process.platform;
76
+ let cmd;
77
+ let args;
78
+ if (platform === 'darwin') {
79
+ cmd = 'open';
80
+ args = [url];
81
+ }
82
+ else if (platform === 'win32') {
83
+ cmd = 'cmd';
84
+ args = ['/c', 'start', '""', url];
85
+ }
86
+ else {
87
+ cmd = 'xdg-open';
88
+ args = [url];
89
+ }
90
+ execFile(cmd, args, (err) => {
91
+ if (err)
92
+ reject(err);
93
+ else
94
+ resolve();
95
+ });
96
+ });
97
+ }
98
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,MAAM,CAAA;AAEnC,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AACxC,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAA;AAGtD,MAAM,gBAAgB,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAA,CAAC,YAAY;AAEnD,MAAM,YAAY,GAAG;;;;;;;CAOpB,CAAA;AAQD;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,WAA4B,EAC5B,gBAAgD,WAAW;IAE3D,MAAM,OAAO,GAAG,YAAY,CAAC,WAAW,CAAC,CAAA;IACzC,IAAI,CAAC,OAAO,EAAE,QAAQ,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CAAC,wBAAwB,WAAW,EAAE,CAAC,CAAA;IACxD,CAAC;IACD,MAAM,WAAW,GAAG,OAAO,CAAC,QAAQ,CAAA;IAEpC,MAAM,SAAS,GAAG,MAAM,IAAI,OAAO,CAAS,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QAC9D,MAAM,MAAM,GAAG,YAAY,CAAC,CAAC,GAAoB,EAAE,GAAmB,EAAE,EAAE;YACxE,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,GAAG,IAAI,GAAG,EAAE,kBAAkB,CAAC,CAAA;YACvD,IAAI,GAAG,CAAC,QAAQ,KAAK,WAAW,EAAE,CAAC;gBACjC,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAA;gBAClB,GAAG,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA;gBACpB,OAAM;YACR,CAAC;YAED,MAAM,GAAG,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,aAAa,CAAC,CAAA;YAC/C,IAAI,CAAC,GAAG,EAAE,CAAC;gBACT,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAA;gBAClB,GAAG,CAAC,GAAG,CAAC,+BAA+B,CAAC,CAAA;gBACxC,OAAM;YACR,CAAC;YAED,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,WAAW,EAAE,CAAC,CAAA;YACnD,GAAG,CAAC,GAAG,CAAC,YAAY,CAAC,CAAA;YAErB,YAAY,CAAC,OAAO,CAAC,CAAA;YACrB,MAAM,CAAC,KAAK,EAAE,CAAA;YACd,OAAO,CAAC,GAAG,CAAC,CAAA;QACd,CAAC,CAAC,CAAA;QAEF,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE;YAC9B,MAAM,CAAC,KAAK,EAAE,CAAA;YACd,MAAM,CAAC,IAAI,KAAK,CAAC,oDAAoD,CAAC,CAAC,CAAA;QACzE,CAAC,EAAE,gBAAgB,CAAC,CAAA;QAEpB,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,WAAW,EAAE,GAAG,EAAE;YACjC,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,EAAE,CAAA;YAC7B,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;gBACtC,YAAY,CAAC,OAAO,CAAC,CAAA;gBACrB,MAAM,CAAC,KAAK,EAAE,CAAA;gBACd,MAAM,CAAC,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAC,CAAA;gBACjD,OAAM;YACR,CAAC;YAED,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAA;YACtB,MAAM,WAAW,GAAG,kBAAkB,CAAC,oBAAoB,IAAI,WAAW,CAAC,CAAA;YAC3E,MAAM,QAAQ,GAAG,GAAG,WAAW,0BAA0B,WAAW,EAAE,CAAA;YAEtE,aAAa,CAAC,QAAQ,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE;gBACjC,sEAAsE;YACxE,CAAC,CAAC,CAAA;QACJ,CAAC,CAAC,CAAA;QAEF,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;YACzB,YAAY,CAAC,OAAO,CAAC,CAAA;YACrB,MAAM,CAAC,IAAI,KAAK,CAAC,iCAAiC,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC,CAAA;QACnE,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEF,OAAO;QACL,SAAS;QACT,WAAW;QACX,QAAQ,EAAE,GAAG,WAAW,WAAW;KACpC,CAAA;AACH,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,GAAW;IACrC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAA;QACjC,IAAI,GAAW,CAAA;QACf,IAAI,IAAc,CAAA;QAClB,IAAI,QAAQ,KAAK,QAAQ,EAAE,CAAC;YAC1B,GAAG,GAAG,MAAM,CAAA;YACZ,IAAI,GAAG,CAAC,GAAG,CAAC,CAAA;QACd,CAAC;aAAM,IAAI,QAAQ,KAAK,OAAO,EAAE,CAAC;YAChC,GAAG,GAAG,KAAK,CAAA;YACX,IAAI,GAAG,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,CAAC,CAAA;QACnC,CAAC;aAAM,CAAC;YACN,GAAG,GAAG,UAAU,CAAA;YAChB,IAAI,GAAG,CAAC,GAAG,CAAC,CAAA;QACd,CAAC;QACD,QAAQ,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,GAAG,EAAE,EAAE;YAC1B,IAAI,GAAG;gBAAE,MAAM,CAAC,GAAG,CAAC,CAAA;;gBACf,OAAO,EAAE,CAAA;QAChB,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;AACJ,CAAC"}
package/dist/config.d.ts CHANGED
@@ -1,19 +1,19 @@
1
1
  import { z } from 'zod';
2
2
  import { Payments } from '@nevermined-io/payments';
3
3
  export declare const NeverminedPluginConfigSchema: z.ZodObject<{
4
- nvmApiKey: z.ZodString;
4
+ nvmApiKey: z.ZodOptional<z.ZodString>;
5
5
  environment: z.ZodDefault<z.ZodEnum<["sandbox", "live"]>>;
6
6
  planId: z.ZodOptional<z.ZodString>;
7
7
  agentId: z.ZodOptional<z.ZodString>;
8
8
  creditsPerRequest: z.ZodDefault<z.ZodNumber>;
9
9
  }, "strip", z.ZodTypeAny, {
10
- nvmApiKey: string;
11
10
  environment: "sandbox" | "live";
12
11
  creditsPerRequest: number;
12
+ nvmApiKey?: string | undefined;
13
13
  planId?: string | undefined;
14
14
  agentId?: string | undefined;
15
15
  }, {
16
- nvmApiKey: string;
16
+ nvmApiKey?: string | undefined;
17
17
  environment?: "sandbox" | "live" | undefined;
18
18
  planId?: string | undefined;
19
19
  agentId?: string | undefined;
@@ -21,5 +21,6 @@ export declare const NeverminedPluginConfigSchema: z.ZodObject<{
21
21
  }>;
22
22
  export type NeverminedPluginConfig = z.infer<typeof NeverminedPluginConfigSchema>;
23
23
  export declare function validateConfig(raw: unknown): NeverminedPluginConfig;
24
+ export declare function requireApiKey(config: NeverminedPluginConfig): string;
24
25
  export declare function createPaymentsFromConfig(config: NeverminedPluginConfig): Payments;
25
26
  //# sourceMappingURL=config.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAA;AAGlD,eAAO,MAAM,4BAA4B;;;;;;;;;;;;;;;;;;EAMvC,CAAA;AAEF,MAAM,MAAM,sBAAsB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,4BAA4B,CAAC,CAAA;AAEjF,wBAAgB,cAAc,CAAC,GAAG,EAAE,OAAO,GAAG,sBAAsB,CAEnE;AAED,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,sBAAsB,GAAG,QAAQ,CAKjF"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAA;AAGlD,eAAO,MAAM,4BAA4B;;;;;;;;;;;;;;;;;;EAMvC,CAAA;AAEF,MAAM,MAAM,sBAAsB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,4BAA4B,CAAC,CAAA;AAEjF,wBAAgB,cAAc,CAAC,GAAG,EAAE,OAAO,GAAG,sBAAsB,CAEnE;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,sBAAsB,GAAG,MAAM,CAKpE;AAED,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,sBAAsB,GAAG,QAAQ,CAKjF"}
package/dist/config.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { z } from 'zod';
2
2
  import { Payments } from '@nevermined-io/payments';
3
3
  export const NeverminedPluginConfigSchema = z.object({
4
- nvmApiKey: z.string().min(1, 'nvmApiKey is required'),
4
+ nvmApiKey: z.string().optional(),
5
5
  environment: z.enum(['sandbox', 'live']).default('sandbox'),
6
6
  planId: z.string().optional(),
7
7
  agentId: z.string().optional(),
@@ -10,9 +10,15 @@ export const NeverminedPluginConfigSchema = z.object({
10
10
  export function validateConfig(raw) {
11
11
  return NeverminedPluginConfigSchema.parse(raw);
12
12
  }
13
+ export function requireApiKey(config) {
14
+ if (!config.nvmApiKey) {
15
+ throw new Error('Not authenticated. Run nevermined.login or /nvm-login first.');
16
+ }
17
+ return config.nvmApiKey;
18
+ }
13
19
  export function createPaymentsFromConfig(config) {
14
20
  return Payments.getInstance({
15
- nvmApiKey: config.nvmApiKey,
21
+ nvmApiKey: requireApiKey(config),
16
22
  environment: config.environment,
17
23
  });
18
24
  }
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAA;AAGlD,MAAM,CAAC,MAAM,4BAA4B,GAAG,CAAC,CAAC,MAAM,CAAC;IACnD,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,uBAAuB,CAAC;IACrD,WAAW,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC;IAC3D,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC7B,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC9B,iBAAiB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;CAC1D,CAAC,CAAA;AAIF,MAAM,UAAU,cAAc,CAAC,GAAY;IACzC,OAAO,4BAA4B,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;AAChD,CAAC;AAED,MAAM,UAAU,wBAAwB,CAAC,MAA8B;IACrE,OAAO,QAAQ,CAAC,WAAW,CAAC;QAC1B,SAAS,EAAE,MAAM,CAAC,SAAS;QAC3B,WAAW,EAAE,MAAM,CAAC,WAA8B;KACnD,CAAC,CAAA;AACJ,CAAC"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAA;AAGlD,MAAM,CAAC,MAAM,4BAA4B,GAAG,CAAC,CAAC,MAAM,CAAC;IACnD,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAChC,WAAW,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC;IAC3D,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC7B,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC9B,iBAAiB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;CAC1D,CAAC,CAAA;AAIF,MAAM,UAAU,cAAc,CAAC,GAAY;IACzC,OAAO,4BAA4B,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;AAChD,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,MAA8B;IAC1D,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC;QACtB,MAAM,IAAI,KAAK,CAAC,8DAA8D,CAAC,CAAA;IACjF,CAAC;IACD,OAAO,MAAM,CAAC,SAAS,CAAA;AACzB,CAAC;AAED,MAAM,UAAU,wBAAwB,CAAC,MAA8B;IACrE,OAAO,QAAQ,CAAC,WAAW,CAAC;QAC1B,SAAS,EAAE,aAAa,CAAC,MAAM,CAAC;QAChC,WAAW,EAAE,MAAM,CAAC,WAA8B;KACnD,CAAC,CAAA;AACJ,CAAC"}
package/dist/index.d.ts CHANGED
@@ -1,12 +1,14 @@
1
- import { validateConfig, createPaymentsFromConfig } from './config.js';
1
+ import { validateConfig, createPaymentsFromConfig, requireApiKey } from './config.js';
2
2
  import { allTools } from './tools.js';
3
- import type { Payments } from '@nevermined-io/payments';
3
+ import { Payments } from '@nevermined-io/payments';
4
4
  import type { NeverminedPluginConfig } from './config.js';
5
5
  import type { ToolDefinition } from './tools.js';
6
6
  export type { NeverminedPluginConfig, ToolDefinition };
7
- export { validateConfig, createPaymentsFromConfig, allTools };
7
+ export { validateConfig, createPaymentsFromConfig, requireApiKey, allTools };
8
+ export { startLoginFlow, openBrowser } from './auth.js';
8
9
  export interface OpenClawPluginAPI {
9
10
  getConfig(namespace: string): unknown;
11
+ setConfig(namespace: string, key: string, value: unknown): void;
10
12
  registerGatewayMethod(name: string, options: {
11
13
  description: string;
12
14
  params: Array<{
@@ -17,6 +19,23 @@ export interface OpenClawPluginAPI {
17
19
  }>;
18
20
  handler: (params: Record<string, unknown>) => Promise<unknown>;
19
21
  }): void;
22
+ registerCommand(options: {
23
+ name: string;
24
+ description: string;
25
+ acceptsArgs?: boolean;
26
+ requireAuth?: boolean;
27
+ handler: (ctx: CommandContext) => Promise<{
28
+ text: string;
29
+ }>;
30
+ }): void;
31
+ }
32
+ export interface CommandContext {
33
+ senderId: string;
34
+ channel: string;
35
+ isAuthorizedSender: boolean;
36
+ args: string;
37
+ commandBody: string;
38
+ config: Record<string, unknown>;
20
39
  }
21
40
  export interface RegisterOptions {
22
41
  paymentsFactory?: (config: NeverminedPluginConfig) => Payments;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAA;AACtE,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AACrC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAA;AACvD,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAA;AACzD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAEhD,YAAY,EAAE,sBAAsB,EAAE,cAAc,EAAE,CAAA;AACtD,OAAO,EAAE,cAAc,EAAE,wBAAwB,EAAE,QAAQ,EAAE,CAAA;AAE7D,MAAM,WAAW,iBAAiB;IAChC,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAA;IACrC,qBAAqB,CACnB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE;QACP,WAAW,EAAE,MAAM,CAAA;QACnB,MAAM,EAAE,KAAK,CAAC;YACZ,IAAI,EAAE,MAAM,CAAA;YACZ,IAAI,EAAE,MAAM,CAAA;YACZ,WAAW,EAAE,MAAM,CAAA;YACnB,QAAQ,EAAE,OAAO,CAAA;SAClB,CAAC,CAAA;QACF,OAAO,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;KAC/D,GACA,IAAI,CAAA;CACR;AAED,MAAM,WAAW,eAAe;IAC9B,eAAe,CAAC,EAAE,CAAC,MAAM,EAAE,sBAAsB,KAAK,QAAQ,CAAA;CAC/D;AAED,wBAAgB,QAAQ,CAAC,GAAG,EAAE,iBAAiB,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,IAAI,CAoBhF"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,wBAAwB,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AACrF,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAErC,OAAO,EAAE,QAAQ,EAAgB,MAAM,yBAAyB,CAAA;AAEhE,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAA;AACzD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAEhD,YAAY,EAAE,sBAAsB,EAAE,cAAc,EAAE,CAAA;AACtD,OAAO,EAAE,cAAc,EAAE,wBAAwB,EAAE,aAAa,EAAE,QAAQ,EAAE,CAAA;AAC5E,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AAEvD,MAAM,WAAW,iBAAiB;IAChC,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAA;IACrC,SAAS,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAAA;IAC/D,qBAAqB,CACnB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE;QACP,WAAW,EAAE,MAAM,CAAA;QACnB,MAAM,EAAE,KAAK,CAAC;YACZ,IAAI,EAAE,MAAM,CAAA;YACZ,IAAI,EAAE,MAAM,CAAA;YACZ,WAAW,EAAE,MAAM,CAAA;YACnB,QAAQ,EAAE,OAAO,CAAA;SAClB,CAAC,CAAA;QACF,OAAO,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;KAC/D,GACA,IAAI,CAAA;IACP,eAAe,CAAC,OAAO,EAAE;QACvB,IAAI,EAAE,MAAM,CAAA;QACZ,WAAW,EAAE,MAAM,CAAA;QACnB,WAAW,CAAC,EAAE,OAAO,CAAA;QACrB,WAAW,CAAC,EAAE,OAAO,CAAA;QACrB,OAAO,EAAE,CAAC,GAAG,EAAE,cAAc,KAAK,OAAO,CAAC;YAAE,IAAI,EAAE,MAAM,CAAA;SAAE,CAAC,CAAA;KAC5D,GAAG,IAAI,CAAA;CACT;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAA;IAChB,OAAO,EAAE,MAAM,CAAA;IACf,kBAAkB,EAAE,OAAO,CAAA;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;IACnB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAChC;AAED,MAAM,WAAW,eAAe;IAC9B,eAAe,CAAC,EAAE,CAAC,MAAM,EAAE,sBAAsB,KAAK,QAAQ,CAAA;CAC/D;AAED,wBAAgB,QAAQ,CAAC,GAAG,EAAE,iBAAiB,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,IAAI,CA+GhF"}
package/dist/index.js CHANGED
@@ -1,18 +1,93 @@
1
- import { validateConfig, createPaymentsFromConfig } from './config.js';
1
+ import { validateConfig, createPaymentsFromConfig, requireApiKey } from './config.js';
2
2
  import { allTools } from './tools.js';
3
- export { validateConfig, createPaymentsFromConfig, allTools };
3
+ import { startLoginFlow } from './auth.js';
4
+ export { validateConfig, createPaymentsFromConfig, requireApiKey, allTools };
5
+ export { startLoginFlow, openBrowser } from './auth.js';
4
6
  export function register(api, options) {
5
7
  const rawConfig = api.getConfig('nevermined');
6
8
  const config = validateConfig(rawConfig);
9
+ // Lazy Payments instance — created on first use after authentication
10
+ let payments = null;
7
11
  const factory = options?.paymentsFactory ?? createPaymentsFromConfig;
8
- const payments = factory(config);
12
+ function getPayments() {
13
+ if (!payments) {
14
+ requireApiKey(config);
15
+ payments = factory(config);
16
+ }
17
+ return payments;
18
+ }
19
+ // --- Login/Logout gateway tools ---
20
+ api.registerGatewayMethod('nevermined.login', {
21
+ description: 'Authenticate with Nevermined via browser login to obtain an API key',
22
+ params: [
23
+ { name: 'environment', type: 'string', description: 'Target environment: sandbox or live (default: from config)', required: false },
24
+ ],
25
+ handler: async (params) => {
26
+ const env = params.environment || config.environment || 'sandbox';
27
+ const result = await startLoginFlow(env);
28
+ config.nvmApiKey = result.nvmApiKey;
29
+ config.environment = result.environment;
30
+ payments = null; // Reset so next call creates a fresh instance
31
+ api.setConfig('nevermined', 'nvmApiKey', result.nvmApiKey);
32
+ api.setConfig('nevermined', 'environment', result.environment);
33
+ return {
34
+ authenticated: true,
35
+ environment: result.environment,
36
+ };
37
+ },
38
+ });
39
+ api.registerGatewayMethod('nevermined.logout', {
40
+ description: 'Log out from Nevermined by removing the stored API key',
41
+ params: [],
42
+ handler: async () => {
43
+ config.nvmApiKey = undefined;
44
+ payments = null;
45
+ api.setConfig('nevermined', 'nvmApiKey', '');
46
+ return { authenticated: false };
47
+ },
48
+ });
49
+ // --- Slash commands for chat channels ---
50
+ api.registerCommand({
51
+ name: 'nvm-login',
52
+ description: 'Authenticate with Nevermined via browser login',
53
+ acceptsArgs: true,
54
+ requireAuth: true,
55
+ handler: async (ctx) => {
56
+ try {
57
+ const env = (ctx.args?.trim() || config.environment || 'sandbox');
58
+ const result = await startLoginFlow(env);
59
+ config.nvmApiKey = result.nvmApiKey;
60
+ config.environment = result.environment;
61
+ payments = null;
62
+ api.setConfig('nevermined', 'nvmApiKey', result.nvmApiKey);
63
+ api.setConfig('nevermined', 'environment', result.environment);
64
+ return { text: `Authenticated with Nevermined (${result.environment}). You can now use payment tools.` };
65
+ }
66
+ catch (err) {
67
+ const message = err instanceof Error ? err.message : String(err);
68
+ return { text: `Login failed: ${message}` };
69
+ }
70
+ },
71
+ });
72
+ api.registerCommand({
73
+ name: 'nvm-logout',
74
+ description: 'Log out from Nevermined',
75
+ requireAuth: true,
76
+ handler: async () => {
77
+ config.nvmApiKey = undefined;
78
+ payments = null;
79
+ api.setConfig('nevermined', 'nvmApiKey', '');
80
+ return { text: 'Logged out from Nevermined. API key has been removed.' };
81
+ },
82
+ });
83
+ // --- Payment tools (require authentication) ---
9
84
  for (const tool of allTools) {
10
85
  api.registerGatewayMethod(tool.name, {
11
86
  description: tool.description,
12
87
  params: tool.params,
13
88
  handler: async (params) => {
14
89
  try {
15
- return await tool.handler(payments, config, params);
90
+ return await tool.handler(getPayments(), config, params);
16
91
  }
17
92
  catch (err) {
18
93
  const message = err instanceof Error ? err.message : String(err);
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAA;AACtE,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAMrC,OAAO,EAAE,cAAc,EAAE,wBAAwB,EAAE,QAAQ,EAAE,CAAA;AAuB7D,MAAM,UAAU,QAAQ,CAAC,GAAsB,EAAE,OAAyB;IACxE,MAAM,SAAS,GAAG,GAAG,CAAC,SAAS,CAAC,YAAY,CAAC,CAAA;IAC7C,MAAM,MAAM,GAAG,cAAc,CAAC,SAAS,CAAC,CAAA;IACxC,MAAM,OAAO,GAAG,OAAO,EAAE,eAAe,IAAI,wBAAwB,CAAA;IACpE,MAAM,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;IAEhC,KAAK,MAAM,IAAI,IAAI,QAAQ,EAAE,CAAC;QAC5B,GAAG,CAAC,qBAAqB,CAAC,IAAI,CAAC,IAAI,EAAE;YACnC,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE;gBACxB,IAAI,CAAC;oBACH,OAAO,MAAM,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;gBACrD,CAAC;gBAAC,OAAO,GAAG,EAAE,CAAC;oBACb,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;oBAChE,MAAM,IAAI,KAAK,CAAC,gBAAgB,IAAI,CAAC,IAAI,YAAY,OAAO,EAAE,CAAC,CAAA;gBACjE,CAAC;YACH,CAAC;SACF,CAAC,CAAA;IACJ,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -5,8 +5,8 @@
5
5
  "configSchema": {
6
6
  "nvmApiKey": {
7
7
  "type": "string",
8
- "required": true,
9
- "description": "Your Nevermined API key"
8
+ "required": false,
9
+ "description": "Your Nevermined API key (optional — use /nvm-login to authenticate via browser)"
10
10
  },
11
11
  "environment": {
12
12
  "type": "string",
@@ -34,7 +34,7 @@
34
34
  "nvmApiKey": {
35
35
  "sensitive": true,
36
36
  "label": "Nevermined API Key",
37
- "placeholder": "sandbox:eyJhbG..."
37
+ "placeholder": "sandbox:eyJhbG... (or use /nvm-login)"
38
38
  },
39
39
  "environment": {
40
40
  "label": "Environment"
@@ -48,9 +48,21 @@
48
48
  "placeholder": "did:nv:..."
49
49
  }
50
50
  },
51
+ "commands": [
52
+ {
53
+ "name": "nvm-login",
54
+ "description": "Authenticate with Nevermined via browser login"
55
+ },
56
+ {
57
+ "name": "nvm-logout",
58
+ "description": "Log out from Nevermined"
59
+ }
60
+ ],
51
61
  "skills": ["skills/nevermined/SKILL.md"],
52
62
  "gateway": {
53
63
  "methods": [
64
+ "nevermined.login",
65
+ "nevermined.logout",
54
66
  "nevermined.checkBalance",
55
67
  "nevermined.getAccessToken",
56
68
  "nevermined.orderPlan",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nevermined-io/openclaw-plugin",
3
- "version": "1.0.11-rc.1",
3
+ "version": "1.0.11",
4
4
  "description": "OpenClaw plugin for Nevermined — exposes subscriber and builder tools as gateway methods",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -2,13 +2,29 @@
2
2
  metadata:
3
3
  openclaw:
4
4
  requires:
5
- config: ["plugins.nevermined.nvmApiKey"]
5
+ config: ["plugins.nevermined"]
6
6
  ---
7
7
 
8
8
  # Nevermined Tools
9
9
 
10
10
  This plugin provides gateway tools for interacting with Nevermined AI agent payments.
11
11
 
12
+ ## Authentication
13
+
14
+ ### `/nvm-login [environment]`
15
+ Authenticate with Nevermined via browser login. Opens a browser window to obtain an API key.
16
+ - `environment` (optional) — `sandbox` or `live` (default: from config)
17
+
18
+ ### `/nvm-logout`
19
+ Log out from Nevermined and remove the stored API key.
20
+
21
+ ### `nevermined.login`
22
+ Gateway method equivalent of `/nvm-login`.
23
+ - `environment` (optional)
24
+
25
+ ### `nevermined.logout`
26
+ Gateway method equivalent of `/nvm-logout`.
27
+
12
28
  ## Subscriber Tools
13
29
 
14
30
  ### `nevermined.checkBalance`