@nevermined-io/openclaw-plugin 1.0.11 → 1.0.13
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/dist/auth.d.ts +13 -0
- package/dist/auth.d.ts.map +1 -1
- package/dist/auth.js +30 -1
- package/dist/auth.js.map +1 -1
- package/dist/index.d.ts +42 -22
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +91 -91
- package/dist/index.js.map +1 -1
- package/dist/tools.d.ts +16 -9
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +228 -215
- package/dist/tools.js.map +1 -1
- package/docs/commands.md +164 -0
- package/docs/getting-started.md +71 -0
- package/docs/links.md +38 -0
- package/docs/setup.md +64 -0
- package/openclaw.plugin.json +27 -68
- package/package.json +7 -1
package/dist/auth.d.ts
CHANGED
|
@@ -4,6 +4,19 @@ export interface LoginResult {
|
|
|
4
4
|
environment: string;
|
|
5
5
|
loginUrl: string;
|
|
6
6
|
}
|
|
7
|
+
/**
|
|
8
|
+
* Returns the Nevermined login URL for a given environment.
|
|
9
|
+
*/
|
|
10
|
+
export declare function getLoginUrl(environment: EnvironmentName): string;
|
|
11
|
+
/**
|
|
12
|
+
* Returns the API key settings URL for a given environment.
|
|
13
|
+
*/
|
|
14
|
+
export declare function getApiKeyUrl(environment: EnvironmentName): string;
|
|
15
|
+
/**
|
|
16
|
+
* Checks whether a string looks like a Nevermined API key.
|
|
17
|
+
* API keys have the format "environment:base64token".
|
|
18
|
+
*/
|
|
19
|
+
export declare function looksLikeApiKey(value: string): boolean;
|
|
7
20
|
/**
|
|
8
21
|
* Starts a one-shot HTTP server, opens the Nevermined login page in the browser,
|
|
9
22
|
* and resolves with the API key once the callback is received.
|
package/dist/auth.d.ts.map
CHANGED
|
@@ -1 +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,
|
|
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;;GAEG;AACH,wBAAgB,WAAW,CAAC,WAAW,EAAE,eAAe,GAAG,MAAM,CAMhE;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,WAAW,EAAE,eAAe,GAAG,MAAM,CAMjE;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAEtD;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,CAmEtB;AAED,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAoBtD"}
|
package/dist/auth.js
CHANGED
|
@@ -10,6 +10,33 @@ const SUCCESS_HTML = `
|
|
|
10
10
|
</div>
|
|
11
11
|
</body></html>
|
|
12
12
|
`;
|
|
13
|
+
/**
|
|
14
|
+
* Returns the Nevermined login URL for a given environment.
|
|
15
|
+
*/
|
|
16
|
+
export function getLoginUrl(environment) {
|
|
17
|
+
const envInfo = Environments[environment];
|
|
18
|
+
if (!envInfo?.frontend) {
|
|
19
|
+
throw new Error(`Unknown environment: ${environment}`);
|
|
20
|
+
}
|
|
21
|
+
return `${envInfo.frontend}/login`;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Returns the API key settings URL for a given environment.
|
|
25
|
+
*/
|
|
26
|
+
export function getApiKeyUrl(environment) {
|
|
27
|
+
const envInfo = Environments[environment];
|
|
28
|
+
if (!envInfo?.frontend) {
|
|
29
|
+
throw new Error(`Unknown environment: ${environment}`);
|
|
30
|
+
}
|
|
31
|
+
return `${envInfo.frontend}/permissions/global-permissions`;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Checks whether a string looks like a Nevermined API key.
|
|
35
|
+
* API keys have the format "environment:base64token".
|
|
36
|
+
*/
|
|
37
|
+
export function looksLikeApiKey(value) {
|
|
38
|
+
return /^(sandbox|live|staging_sandbox|staging_live):/.test(value.trim());
|
|
39
|
+
}
|
|
13
40
|
/**
|
|
14
41
|
* Starts a one-shot HTTP server, opens the Nevermined login page in the browser,
|
|
15
42
|
* and resolves with the API key once the callback is received.
|
|
@@ -56,7 +83,9 @@ export async function startLoginFlow(environment, openBrowserFn = openBrowser) {
|
|
|
56
83
|
const callbackUrl = encodeURIComponent(`http://localhost:${port}/callback`);
|
|
57
84
|
const loginUrl = `${frontendUrl}/auth/cli?callback_url=${callbackUrl}`;
|
|
58
85
|
openBrowserFn(loginUrl).catch(() => {
|
|
59
|
-
|
|
86
|
+
clearTimeout(timeout);
|
|
87
|
+
server.close();
|
|
88
|
+
reject(new Error('Could not open browser'));
|
|
60
89
|
});
|
|
61
90
|
});
|
|
62
91
|
server.on('error', (err) => {
|
package/dist/auth.js.map
CHANGED
|
@@ -1 +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,
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,44 +1,64 @@
|
|
|
1
1
|
import { validateConfig, createPaymentsFromConfig, requireApiKey } from './config.js';
|
|
2
|
-
import { allTools } from './tools.js';
|
|
3
2
|
import { Payments } from '@nevermined-io/payments';
|
|
4
3
|
import type { NeverminedPluginConfig } from './config.js';
|
|
5
|
-
|
|
6
|
-
export
|
|
7
|
-
export { validateConfig, createPaymentsFromConfig, requireApiKey, allTools };
|
|
4
|
+
export type { NeverminedPluginConfig };
|
|
5
|
+
export { validateConfig, createPaymentsFromConfig, requireApiKey };
|
|
8
6
|
export { startLoginFlow, openBrowser } from './auth.js';
|
|
7
|
+
/**
|
|
8
|
+
* Minimal subset of the OpenClaw Plugin API used by this plugin.
|
|
9
|
+
*/
|
|
9
10
|
export interface OpenClawPluginAPI {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
11
|
+
id: string;
|
|
12
|
+
pluginConfig?: Record<string, unknown>;
|
|
13
|
+
config: Record<string, unknown>;
|
|
14
|
+
logger: {
|
|
15
|
+
info: (msg: string) => void;
|
|
16
|
+
warn: (msg: string) => void;
|
|
17
|
+
error: (msg: string) => void;
|
|
18
|
+
};
|
|
19
|
+
registerTool(tool: unknown, opts?: {
|
|
20
|
+
optional?: boolean;
|
|
21
|
+
names?: string[];
|
|
21
22
|
}): void;
|
|
22
|
-
registerCommand(
|
|
23
|
+
registerCommand(command: {
|
|
23
24
|
name: string;
|
|
24
25
|
description: string;
|
|
25
26
|
acceptsArgs?: boolean;
|
|
26
27
|
requireAuth?: boolean;
|
|
27
|
-
handler: (ctx: CommandContext) => Promise<
|
|
28
|
-
text: string;
|
|
29
|
-
}>;
|
|
28
|
+
handler: (ctx: CommandContext) => Promise<CommandResult> | CommandResult;
|
|
30
29
|
}): void;
|
|
30
|
+
registerGatewayMethod(method: string, handler: unknown): void;
|
|
31
31
|
}
|
|
32
32
|
export interface CommandContext {
|
|
33
|
-
senderId
|
|
33
|
+
senderId?: string;
|
|
34
34
|
channel: string;
|
|
35
35
|
isAuthorizedSender: boolean;
|
|
36
|
-
args
|
|
36
|
+
args?: string;
|
|
37
37
|
commandBody: string;
|
|
38
38
|
config: Record<string, unknown>;
|
|
39
39
|
}
|
|
40
|
+
export interface CommandResult {
|
|
41
|
+
text: string;
|
|
42
|
+
}
|
|
40
43
|
export interface RegisterOptions {
|
|
41
44
|
paymentsFactory?: (config: NeverminedPluginConfig) => Payments;
|
|
42
45
|
}
|
|
43
|
-
export
|
|
46
|
+
export interface ToolContext {
|
|
47
|
+
config?: Record<string, unknown>;
|
|
48
|
+
workspaceDir?: string;
|
|
49
|
+
agentDir?: string;
|
|
50
|
+
agentId?: string;
|
|
51
|
+
sessionKey?: string;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* OpenClaw plugin definition object.
|
|
55
|
+
* Exports id, name, description, and a register function.
|
|
56
|
+
*/
|
|
57
|
+
declare const neverminedPlugin: {
|
|
58
|
+
id: string;
|
|
59
|
+
name: string;
|
|
60
|
+
description: string;
|
|
61
|
+
register(api: OpenClawPluginAPI, options?: RegisterOptions): void;
|
|
62
|
+
};
|
|
63
|
+
export default neverminedPlugin;
|
|
44
64
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
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;
|
|
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;AAGrF,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAA;AAElD,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAA;AAEzD,YAAY,EAAE,sBAAsB,EAAE,CAAA;AACtC,OAAO,EAAE,cAAc,EAAE,wBAAwB,EAAE,aAAa,EAAE,CAAA;AAClE,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AAEvD;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAA;IACV,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACtC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC/B,MAAM,EAAE;QACN,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAA;QAC3B,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAA;QAC3B,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAA;KAC7B,CAAA;IACD,YAAY,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,GAAG,IAAI,CAAA;IAClF,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,aAAa,CAAC,GAAG,aAAa,CAAA;KACzE,GAAG,IAAI,CAAA;IACR,qBAAqB,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI,CAAA;CAC9D;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,OAAO,EAAE,MAAM,CAAA;IACf,kBAAkB,EAAE,OAAO,CAAA;IAC3B,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,WAAW,EAAE,MAAM,CAAA;IACnB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAChC;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAA;CACb;AAED,MAAM,WAAW,eAAe;IAC9B,eAAe,CAAC,EAAE,CAAC,MAAM,EAAE,sBAAsB,KAAK,QAAQ,CAAA;CAC/D;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAChC,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAED;;;GAGG;AACH,QAAA,MAAM,gBAAgB;;;;kBAKN,iBAAiB,YAAY,eAAe,GAAG,IAAI;CAuGlE,CAAA;AAED,eAAe,gBAAgB,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -1,100 +1,100 @@
|
|
|
1
1
|
import { validateConfig, createPaymentsFromConfig, requireApiKey } from './config.js';
|
|
2
|
-
import {
|
|
3
|
-
import { startLoginFlow } from './auth.js';
|
|
4
|
-
export { validateConfig, createPaymentsFromConfig, requireApiKey
|
|
2
|
+
import { createTools } from './tools.js';
|
|
3
|
+
import { startLoginFlow, looksLikeApiKey, getLoginUrl, getApiKeyUrl } from './auth.js';
|
|
4
|
+
export { validateConfig, createPaymentsFromConfig, requireApiKey };
|
|
5
5
|
export { startLoginFlow, openBrowser } from './auth.js';
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
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.` };
|
|
6
|
+
/**
|
|
7
|
+
* OpenClaw plugin definition object.
|
|
8
|
+
* Exports id, name, description, and a register function.
|
|
9
|
+
*/
|
|
10
|
+
const neverminedPlugin = {
|
|
11
|
+
id: 'nevermined',
|
|
12
|
+
name: '@nevermined-io/openclaw-plugin',
|
|
13
|
+
description: 'Nevermined plugin for OpenClaw — AI agent payments and access control',
|
|
14
|
+
register(api, options) {
|
|
15
|
+
const config = validateConfig(api.pluginConfig ?? {});
|
|
16
|
+
// Lazy Payments instance — created on first use after authentication
|
|
17
|
+
let payments = null;
|
|
18
|
+
const factory = options?.paymentsFactory ?? createPaymentsFromConfig;
|
|
19
|
+
function getPayments() {
|
|
20
|
+
if (!payments) {
|
|
21
|
+
requireApiKey(config);
|
|
22
|
+
payments = factory(config);
|
|
65
23
|
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
handler: async (
|
|
24
|
+
return payments;
|
|
25
|
+
}
|
|
26
|
+
// --- Register tools via factory function ---
|
|
27
|
+
// OpenClaw calls the factory per agent session, providing context.
|
|
28
|
+
// We return the full tool array each time.
|
|
29
|
+
const toolNames = [
|
|
30
|
+
'nevermined_checkBalance',
|
|
31
|
+
'nevermined_getAccessToken',
|
|
32
|
+
'nevermined_orderPlan',
|
|
33
|
+
'nevermined_queryAgent',
|
|
34
|
+
'nevermined_registerAgent',
|
|
35
|
+
'nevermined_createPlan',
|
|
36
|
+
'nevermined_listPlans',
|
|
37
|
+
];
|
|
38
|
+
api.registerTool((_ctx) => createTools(getPayments, config), { names: toolNames });
|
|
39
|
+
api.logger.info(`Registered ${toolNames.length} Nevermined payment tools`);
|
|
40
|
+
// --- Slash commands for chat channels ---
|
|
41
|
+
api.registerCommand({
|
|
42
|
+
name: 'nvm_login',
|
|
43
|
+
description: 'Authenticate with Nevermined. Usage: /nvm_login [environment] or /nvm_login <api-key>',
|
|
44
|
+
acceptsArgs: true,
|
|
45
|
+
requireAuth: true,
|
|
46
|
+
handler: async (ctx) => {
|
|
47
|
+
const input = ctx.args?.trim() || '';
|
|
48
|
+
// --- Flow 1: User pasted an API key directly ---
|
|
49
|
+
if (looksLikeApiKey(input)) {
|
|
50
|
+
const apiKey = input;
|
|
51
|
+
const keyEnv = apiKey.split(':')[0];
|
|
52
|
+
config.nvmApiKey = apiKey;
|
|
53
|
+
config.environment = keyEnv;
|
|
54
|
+
payments = null;
|
|
55
|
+
api.logger.info(`Nevermined: authenticated via API key (${keyEnv})`);
|
|
56
|
+
return { text: `Authenticated with Nevermined (${keyEnv}). You can now use payment tools.` };
|
|
57
|
+
}
|
|
58
|
+
// --- Flow 2: Try browser login, fall back to manual instructions ---
|
|
59
|
+
const env = (input || config.environment || 'sandbox');
|
|
89
60
|
try {
|
|
90
|
-
|
|
61
|
+
const result = await startLoginFlow(env);
|
|
62
|
+
config.nvmApiKey = result.nvmApiKey;
|
|
63
|
+
config.environment = result.environment;
|
|
64
|
+
payments = null;
|
|
65
|
+
return { text: `Authenticated with Nevermined (${result.environment}). You can now use payment tools.` };
|
|
91
66
|
}
|
|
92
|
-
catch (
|
|
93
|
-
|
|
94
|
-
|
|
67
|
+
catch (_err) {
|
|
68
|
+
// Browser login failed (headless server, timeout, etc.)
|
|
69
|
+
// Provide manual instructions
|
|
70
|
+
const loginUrl = getLoginUrl(env);
|
|
71
|
+
const apiKeyUrl = getApiKeyUrl(env);
|
|
72
|
+
return {
|
|
73
|
+
text: [
|
|
74
|
+
`I couldn't open a browser for automatic login. Here's how to authenticate manually:`,
|
|
75
|
+
``,
|
|
76
|
+
`1. Open this URL and log in: ${loginUrl}`,
|
|
77
|
+
`2. Go to API Keys to get your API key: ${apiKeyUrl}`,
|
|
78
|
+
`3. Copy the API key and send it here:`,
|
|
79
|
+
` /nvm_login <your-api-key>`,
|
|
80
|
+
``,
|
|
81
|
+
`API keys look like: ${env}:eyJhbG...`,
|
|
82
|
+
].join('\n'),
|
|
83
|
+
};
|
|
95
84
|
}
|
|
96
85
|
},
|
|
97
86
|
});
|
|
98
|
-
|
|
99
|
-
|
|
87
|
+
api.registerCommand({
|
|
88
|
+
name: 'nvm_logout',
|
|
89
|
+
description: 'Log out from Nevermined',
|
|
90
|
+
requireAuth: true,
|
|
91
|
+
handler: async () => {
|
|
92
|
+
config.nvmApiKey = undefined;
|
|
93
|
+
payments = null;
|
|
94
|
+
return { text: 'Logged out from Nevermined. API key has been removed.' };
|
|
95
|
+
},
|
|
96
|
+
});
|
|
97
|
+
},
|
|
98
|
+
};
|
|
99
|
+
export default neverminedPlugin;
|
|
100
100
|
//# sourceMappingURL=index.js.map
|
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,aAAa,EAAE,MAAM,aAAa,CAAA;AACrF,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/tools.d.ts
CHANGED
|
@@ -1,16 +1,23 @@
|
|
|
1
1
|
import type { Payments } from '@nevermined-io/payments';
|
|
2
2
|
import type { NeverminedPluginConfig } from './config.js';
|
|
3
|
-
|
|
3
|
+
/**
|
|
4
|
+
* Creates all Nevermined payment tools for the OpenClaw plugin.
|
|
5
|
+
* Each tool is an object with { name, description, parameters, execute }
|
|
6
|
+
* compatible with the OpenClaw AnyAgentTool interface.
|
|
7
|
+
*/
|
|
8
|
+
export declare function createTools(getPayments: () => Payments, config: NeverminedPluginConfig): ToolObject[];
|
|
9
|
+
interface ToolObject {
|
|
4
10
|
name: string;
|
|
5
|
-
|
|
11
|
+
label: string;
|
|
6
12
|
description: string;
|
|
7
|
-
|
|
13
|
+
parameters: Record<string, unknown>;
|
|
14
|
+
execute: (_id: string, params: Record<string, unknown>) => Promise<ToolResult>;
|
|
8
15
|
}
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
16
|
+
interface ToolResult {
|
|
17
|
+
content: Array<{
|
|
18
|
+
type: string;
|
|
19
|
+
text: string;
|
|
20
|
+
}>;
|
|
14
21
|
}
|
|
15
|
-
export
|
|
22
|
+
export {};
|
|
16
23
|
//# sourceMappingURL=tools.d.ts.map
|
package/dist/tools.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAA;AACvD,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAA;AAEzD,
|
|
1
|
+
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAA;AACvD,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAA;AAEzD;;;;GAIG;AACH,wBAAgB,WAAW,CACzB,WAAW,EAAE,MAAM,QAAQ,EAC3B,MAAM,EAAE,sBAAsB,GAC7B,UAAU,EAAE,CA2Od;AAID,UAAU,UAAU;IAClB,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,EAAE,MAAM,CAAA;IACnB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACnC,OAAO,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,UAAU,CAAC,CAAA;CAC/E;AAED,UAAU,UAAU;IAClB,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAC/C"}
|