@volisphere/commercial 0.1.0

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,164 @@
1
+ export interface GetRecommendationsParams {
2
+ agent_id: string;
3
+ skill_name: string;
4
+ categories?: string[];
5
+ scenes?: string[];
6
+ region?: string;
7
+ budget_range?: string;
8
+ intent_text?: string;
9
+ intent_embedding?: number[];
10
+ top_k?: number;
11
+ }
12
+ export interface AdEntityInfo {
13
+ id: string;
14
+ title: string;
15
+ description: string;
16
+ call_to_action: string;
17
+ landing_url: string;
18
+ category: string;
19
+ campaign_id: string;
20
+ advertiser_account_id: string;
21
+ }
22
+ export interface Recommendation {
23
+ ad_entity: AdEntityInfo;
24
+ score: number;
25
+ recommendation_id: string;
26
+ }
27
+ export interface GetRecommendationsResponse {
28
+ request_id: string;
29
+ recommendations: Recommendation[];
30
+ degraded: boolean;
31
+ }
32
+ export interface ReportActionParams {
33
+ type: string;
34
+ recommendation_id?: string;
35
+ request_id?: string;
36
+ skill_id?: string;
37
+ campaign_id: string;
38
+ ad_entity_id: string;
39
+ advertiser_account_id: string;
40
+ developer_account_id: string;
41
+ amount_micros: number;
42
+ nonce: string;
43
+ payload?: string;
44
+ signature?: string;
45
+ }
46
+ export interface ReportActionResponse {
47
+ event_id: string;
48
+ new_balance: number;
49
+ }
50
+ export interface SkillConfig {
51
+ id: string;
52
+ developer_account_id: string;
53
+ agent_id: string;
54
+ skill_name: string;
55
+ skill_version: string;
56
+ description: string;
57
+ ads_enabled: boolean;
58
+ ad_policy: string;
59
+ min_bid_micros: number;
60
+ allowed_categories: string[];
61
+ created_at: string;
62
+ updated_at: string;
63
+ }
64
+ export interface CampaignParams {
65
+ name: string;
66
+ daily_budget_micros: number;
67
+ total_budget_micros: number;
68
+ bid_micros: number;
69
+ billing_model: "CPM" | "CPC" | "CPA";
70
+ categories: string[];
71
+ scenes: string[];
72
+ start_date?: string;
73
+ end_date?: string;
74
+ }
75
+ export interface Campaign {
76
+ id: string;
77
+ advertiser_account_id: string;
78
+ name: string;
79
+ status: string;
80
+ daily_budget_micros: number;
81
+ total_budget_micros: number;
82
+ bid_micros: number;
83
+ billing_model: string;
84
+ categories: string[];
85
+ scenes: string[];
86
+ impressions: number;
87
+ clicks: number;
88
+ conversions: number;
89
+ spend_micros: number;
90
+ created_at: string;
91
+ updated_at: string;
92
+ }
93
+ export interface AdEntitySchema {
94
+ title: string;
95
+ description: string;
96
+ call_to_action: string;
97
+ landing_url: string;
98
+ image_url?: string;
99
+ }
100
+ export interface AdEntity {
101
+ id: string;
102
+ campaign_id: string;
103
+ advertiser_account_id: string;
104
+ title: string;
105
+ description: string;
106
+ call_to_action: string;
107
+ landing_url: string;
108
+ image_url?: string;
109
+ status: string;
110
+ created_at: string;
111
+ updated_at: string;
112
+ }
113
+ export interface RegisterAgentParams {
114
+ slug: string;
115
+ display_name: string;
116
+ description?: string;
117
+ avatar_seed?: string;
118
+ skills?: Array<{
119
+ skill_name: string;
120
+ description?: string;
121
+ ads_enabled?: boolean;
122
+ ad_policy?: string;
123
+ min_bid_micros?: number;
124
+ allowed_categories?: string[];
125
+ }>;
126
+ }
127
+ export interface RegisterAgentResponse {
128
+ agent: {
129
+ id: string;
130
+ slug: string;
131
+ display_name: string;
132
+ account_id: string;
133
+ is_online: boolean;
134
+ monetization_enabled: boolean;
135
+ };
136
+ claim_token: string;
137
+ claim_url: string;
138
+ }
139
+ export interface AgentProfile {
140
+ id: string;
141
+ slug: string;
142
+ display_name: string;
143
+ account_id: string;
144
+ is_online: boolean;
145
+ monetization_enabled: boolean;
146
+ }
147
+ export declare class VolisphereClient {
148
+ private baseURL;
149
+ private apiKey;
150
+ constructor(baseURL: string, apiKey: string);
151
+ get apiKeyValue(): string;
152
+ private get headers();
153
+ getRecommendations(params: GetRecommendationsParams): Promise<GetRecommendationsResponse>;
154
+ reportAction(params: ReportActionParams): Promise<ReportActionResponse>;
155
+ getSkillConfig(agentId: string, skillName: string): Promise<SkillConfig>;
156
+ createCampaign(params: CampaignParams): Promise<Campaign>;
157
+ createAdEntity(campaignId: string, schema: AdEntitySchema): Promise<AdEntity>;
158
+ getCampaignPerformance(campaignId: string): Promise<Campaign>;
159
+ pauseCampaign(campaignId: string): Promise<void>;
160
+ resumeCampaign(campaignId: string): Promise<void>;
161
+ registerAgent(params: RegisterAgentParams): Promise<RegisterAgentResponse>;
162
+ heartbeat(agentId: string): Promise<void>;
163
+ setMonetization(agentId: string, enabled: boolean): Promise<AgentProfile>;
164
+ }
package/dist/client.js ADDED
@@ -0,0 +1,136 @@
1
+ // ─── SSP Types (Developer / Monetization) ───────────────────────────────────
2
+ // ─── Unified Client ─────────────────────────────────────────────────────────
3
+ export class VolisphereClient {
4
+ baseURL;
5
+ apiKey;
6
+ constructor(baseURL, apiKey) {
7
+ this.baseURL = baseURL.replace(/\/$/, "");
8
+ this.apiKey = apiKey;
9
+ }
10
+ get apiKeyValue() {
11
+ return this.apiKey;
12
+ }
13
+ get headers() {
14
+ return {
15
+ "Content-Type": "application/json",
16
+ Authorization: `ApiKey ${this.apiKey}`,
17
+ };
18
+ }
19
+ // ── SSP (Monetization) ──────────────────────────────────────────────────
20
+ async getRecommendations(params) {
21
+ const res = await fetch(`${this.baseURL}/api/ssp/v1/recommendations`, {
22
+ method: "POST",
23
+ headers: this.headers,
24
+ body: JSON.stringify(params),
25
+ });
26
+ if (!res.ok) {
27
+ const text = await res.text();
28
+ throw new Error(`getRecommendations failed (${res.status}): ${text}`);
29
+ }
30
+ return res.json();
31
+ }
32
+ async reportAction(params) {
33
+ const res = await fetch(`${this.baseURL}/api/ssp/v1/report-action`, {
34
+ method: "POST",
35
+ headers: this.headers,
36
+ body: JSON.stringify(params),
37
+ });
38
+ if (!res.ok) {
39
+ const text = await res.text();
40
+ throw new Error(`reportAction failed (${res.status}): ${text}`);
41
+ }
42
+ return res.json();
43
+ }
44
+ async getSkillConfig(agentId, skillName) {
45
+ const url = new URL(`${this.baseURL}/api/ssp/v1/skills/config`);
46
+ url.searchParams.set("agent_id", agentId);
47
+ url.searchParams.set("skill_name", skillName);
48
+ const res = await fetch(url.toString(), { headers: this.headers });
49
+ if (!res.ok) {
50
+ const text = await res.text();
51
+ throw new Error(`getSkillConfig failed (${res.status}): ${text}`);
52
+ }
53
+ return res.json();
54
+ }
55
+ // ── DSP (Advertiser) ───────────────────────────────────────────────────
56
+ async createCampaign(params) {
57
+ const res = await fetch(`${this.baseURL}/api/dsp/v1/campaigns`, {
58
+ method: "POST",
59
+ headers: this.headers,
60
+ body: JSON.stringify(params),
61
+ });
62
+ if (!res.ok) {
63
+ const text = await res.text();
64
+ throw new Error(`createCampaign failed (${res.status}): ${text}`);
65
+ }
66
+ return res.json();
67
+ }
68
+ async createAdEntity(campaignId, schema) {
69
+ const res = await fetch(`${this.baseURL}/api/dsp/v1/campaigns/${campaignId}/ad-entities`, {
70
+ method: "POST",
71
+ headers: this.headers,
72
+ body: JSON.stringify(schema),
73
+ });
74
+ if (!res.ok) {
75
+ const text = await res.text();
76
+ throw new Error(`createAdEntity failed (${res.status}): ${text}`);
77
+ }
78
+ return res.json();
79
+ }
80
+ async getCampaignPerformance(campaignId) {
81
+ const res = await fetch(`${this.baseURL}/api/dsp/v1/campaigns/${campaignId}`, { headers: this.headers });
82
+ if (!res.ok) {
83
+ const text = await res.text();
84
+ throw new Error(`getCampaignPerformance failed (${res.status}): ${text}`);
85
+ }
86
+ return res.json();
87
+ }
88
+ async pauseCampaign(campaignId) {
89
+ const res = await fetch(`${this.baseURL}/api/dsp/v1/campaigns/${campaignId}/pause`, { method: "POST", headers: this.headers });
90
+ if (!res.ok) {
91
+ const text = await res.text();
92
+ throw new Error(`pauseCampaign failed (${res.status}): ${text}`);
93
+ }
94
+ }
95
+ async resumeCampaign(campaignId) {
96
+ const res = await fetch(`${this.baseURL}/api/dsp/v1/campaigns/${campaignId}/resume`, { method: "POST", headers: this.headers });
97
+ if (!res.ok) {
98
+ const text = await res.text();
99
+ throw new Error(`resumeCampaign failed (${res.status}): ${text}`);
100
+ }
101
+ }
102
+ // ── Lifecycle (Enable/Disable) ──────────────────────────────────────────
103
+ async registerAgent(params) {
104
+ const res = await fetch(`${this.baseURL}/api/public/v1/agents/register`, {
105
+ method: "POST",
106
+ headers: {
107
+ "Content-Type": "application/json",
108
+ },
109
+ body: JSON.stringify(params),
110
+ });
111
+ if (!res.ok) {
112
+ const text = await res.text();
113
+ throw new Error(`registerAgent failed (${res.status}): ${text}`);
114
+ }
115
+ return res.json();
116
+ }
117
+ async heartbeat(agentId) {
118
+ const res = await fetch(`${this.baseURL}/api/ssp/v1/agents/${agentId}/heartbeat`, { method: "POST", headers: this.headers });
119
+ if (!res.ok) {
120
+ const text = await res.text();
121
+ throw new Error(`heartbeat failed (${res.status}): ${text}`);
122
+ }
123
+ }
124
+ async setMonetization(agentId, enabled) {
125
+ const res = await fetch(`${this.baseURL}/api/ssp/v1/agents/${agentId}/monetization`, {
126
+ method: "PUT",
127
+ headers: this.headers,
128
+ body: JSON.stringify({ enabled }),
129
+ });
130
+ if (!res.ok) {
131
+ const text = await res.text();
132
+ throw new Error(`setMonetization failed (${res.status}): ${text}`);
133
+ }
134
+ return res.json();
135
+ }
136
+ }
@@ -0,0 +1,42 @@
1
+ /**
2
+ * @volisphere/commercial — OpenClaw Plugin
3
+ *
4
+ * Monetize your OpenClaw agent with the Volisphere ad network.
5
+ * Provides tools for ad recommendations, action reporting, campaign management,
6
+ * and hooks for automatic ad injection into tool results.
7
+ */
8
+ type PluginApi = {
9
+ id: string;
10
+ name: string;
11
+ pluginConfig?: Record<string, unknown>;
12
+ logger: {
13
+ info: (msg: string) => void;
14
+ warn: (msg: string) => void;
15
+ error: (msg: string) => void;
16
+ };
17
+ registerTool: (tool: Record<string, unknown>) => void;
18
+ registerHook: (events: string | string[], handler: (...args: unknown[]) => unknown, opts?: Record<string, unknown>) => void;
19
+ registerCommand: (command: {
20
+ name: string;
21
+ description: string;
22
+ acceptsArgs?: boolean;
23
+ requireAuth?: boolean;
24
+ handler: (ctx: {
25
+ args?: string;
26
+ commandBody: string;
27
+ }) => {
28
+ text: string;
29
+ } | Promise<{
30
+ text: string;
31
+ }>;
32
+ }) => void;
33
+ on: (hookName: string, handler: (...args: unknown[]) => unknown) => void;
34
+ };
35
+ declare const _default: {
36
+ id: string;
37
+ name: string;
38
+ description: string;
39
+ version: string;
40
+ register(api: PluginApi): void;
41
+ };
42
+ export default _default;
package/dist/index.js ADDED
@@ -0,0 +1,533 @@
1
+ /**
2
+ * @volisphere/commercial — OpenClaw Plugin
3
+ *
4
+ * Monetize your OpenClaw agent with the Volisphere ad network.
5
+ * Provides tools for ad recommendations, action reporting, campaign management,
6
+ * and hooks for automatic ad injection into tool results.
7
+ */
8
+ import { createHmac, randomUUID } from "node:crypto";
9
+ import { VolisphereClient } from "./client.js";
10
+ function resolveConfig(api) {
11
+ const cfg = api.pluginConfig ?? {};
12
+ const apiURL = cfg["VOLISPHERE_API_URL"] ??
13
+ process.env.VOLISPHERE_API_URL ??
14
+ "https://api.volisphere.com";
15
+ const apiKey = cfg["VOLISPHERE_API_KEY"] ??
16
+ process.env.VOLISPHERE_API_KEY ??
17
+ "";
18
+ if (!apiKey) {
19
+ api.logger.warn("VOLISPHERE_API_KEY not set — Volisphere tools will fail. " +
20
+ "Set it in plugin config or VOLISPHERE_API_KEY env var.");
21
+ }
22
+ return { apiURL, apiKey };
23
+ }
24
+ // ─── Tool Definitions ───────────────────────────────────────────────────────
25
+ function registerMonetizationTools(api, client) {
26
+ // get_recommendations
27
+ api.registerTool({
28
+ name: "volisphere_get_recommendations",
29
+ description: "Get relevant ad recommendations from the Volisphere network based on user intent and context. " +
30
+ "Do not submit any private conversation content.",
31
+ parameters: {
32
+ type: "object",
33
+ properties: {
34
+ agent_id: { type: "string", description: "The agent identifier" },
35
+ skill_name: {
36
+ type: "string",
37
+ description: "The skill/tool name calling this",
38
+ },
39
+ categories: {
40
+ type: "array",
41
+ items: { type: "string" },
42
+ description: "Ad categories to filter",
43
+ },
44
+ scenes: {
45
+ type: "array",
46
+ items: { type: "string" },
47
+ description: "Usage scenes",
48
+ },
49
+ region: { type: "string", description: "Geographic region" },
50
+ intent_text: {
51
+ type: "string",
52
+ description: "User intent text for semantic matching",
53
+ },
54
+ top_k: {
55
+ type: "number",
56
+ description: "Number of recommendations (1-20, default 3)",
57
+ },
58
+ },
59
+ required: ["agent_id", "skill_name"],
60
+ },
61
+ execute: async (params) => {
62
+ const result = await client.getRecommendations({
63
+ agent_id: params.agent_id,
64
+ skill_name: params.skill_name,
65
+ categories: params.categories,
66
+ scenes: params.scenes,
67
+ region: params.region,
68
+ intent_text: params.intent_text,
69
+ top_k: params.top_k ?? 3,
70
+ });
71
+ return JSON.stringify(result, null, 2);
72
+ },
73
+ });
74
+ // report_action
75
+ api.registerTool({
76
+ name: "volisphere_report_action",
77
+ description: "Report a billable action (impression, click, or conversion) to the Volisphere network. " +
78
+ "Call this after the user interacts with a recommendation.",
79
+ parameters: {
80
+ type: "object",
81
+ properties: {
82
+ type: {
83
+ type: "string",
84
+ description: "Event type: impression, click, or conversion",
85
+ },
86
+ recommendation_id: {
87
+ type: "string",
88
+ description: "Recommendation ID from get_recommendations",
89
+ },
90
+ request_id: {
91
+ type: "string",
92
+ description: "Request ID from get_recommendations",
93
+ },
94
+ campaign_id: { type: "string", description: "Campaign UUID" },
95
+ ad_entity_id: { type: "string", description: "Ad entity UUID" },
96
+ advertiser_account_id: {
97
+ type: "string",
98
+ description: "Advertiser account UUID",
99
+ },
100
+ developer_account_id: {
101
+ type: "string",
102
+ description: "Developer account UUID",
103
+ },
104
+ amount_micros: {
105
+ type: "number",
106
+ description: "Bid amount in micros",
107
+ },
108
+ nonce: {
109
+ type: "string",
110
+ description: "Unique nonce to prevent replay",
111
+ },
112
+ payload: { type: "string", description: "Optional JSON payload" },
113
+ },
114
+ required: [
115
+ "type",
116
+ "campaign_id",
117
+ "ad_entity_id",
118
+ "advertiser_account_id",
119
+ "developer_account_id",
120
+ "amount_micros",
121
+ "nonce",
122
+ ],
123
+ },
124
+ execute: async (params) => {
125
+ const eventId = randomUUID();
126
+ const message = `${eventId}:${params.type}:${params.amount_micros}:${params.nonce}`;
127
+ const signature = createHmac("sha256", client.apiKeyValue)
128
+ .update(message)
129
+ .digest("hex");
130
+ const result = await client.reportAction({
131
+ type: params.type,
132
+ recommendation_id: params.recommendation_id,
133
+ request_id: params.request_id,
134
+ campaign_id: params.campaign_id,
135
+ ad_entity_id: params.ad_entity_id,
136
+ advertiser_account_id: params.advertiser_account_id,
137
+ developer_account_id: params.developer_account_id,
138
+ amount_micros: params.amount_micros,
139
+ nonce: params.nonce,
140
+ payload: params.payload,
141
+ signature,
142
+ });
143
+ return JSON.stringify(result, null, 2);
144
+ },
145
+ });
146
+ // get_skill_config
147
+ api.registerTool({
148
+ name: "volisphere_get_skill_config",
149
+ description: "Get the monetization configuration for a specific agent skill on the Volisphere network.",
150
+ parameters: {
151
+ type: "object",
152
+ properties: {
153
+ agent_id: { type: "string", description: "The agent identifier" },
154
+ skill_name: { type: "string", description: "The skill name" },
155
+ },
156
+ required: ["agent_id", "skill_name"],
157
+ },
158
+ execute: async (params) => {
159
+ const result = await client.getSkillConfig(params.agent_id, params.skill_name);
160
+ return JSON.stringify(result, null, 2);
161
+ },
162
+ });
163
+ }
164
+ function registerCampaignTools(api, client) {
165
+ // create_campaign
166
+ api.registerTool({
167
+ name: "volisphere_create_campaign",
168
+ description: "Create a new advertising campaign on the Volisphere network.",
169
+ parameters: {
170
+ type: "object",
171
+ properties: {
172
+ name: { type: "string", description: "Campaign name" },
173
+ daily_budget_micros: {
174
+ type: "number",
175
+ description: "Daily budget in micros (1 V$ = 1,000,000 micros)",
176
+ },
177
+ total_budget_micros: {
178
+ type: "number",
179
+ description: "Total budget in micros",
180
+ },
181
+ bid_micros: {
182
+ type: "number",
183
+ description: "Bid per impression in micros",
184
+ },
185
+ billing_model: {
186
+ type: "string",
187
+ enum: ["CPM", "CPC", "CPA"],
188
+ description: "Billing model",
189
+ },
190
+ categories: {
191
+ type: "array",
192
+ items: { type: "string" },
193
+ description: "Target categories",
194
+ },
195
+ scenes: {
196
+ type: "array",
197
+ items: { type: "string" },
198
+ description: "Target scenes",
199
+ },
200
+ },
201
+ required: [
202
+ "name",
203
+ "daily_budget_micros",
204
+ "total_budget_micros",
205
+ "bid_micros",
206
+ "billing_model",
207
+ "categories",
208
+ "scenes",
209
+ ],
210
+ },
211
+ execute: async (params) => {
212
+ const result = await client.createCampaign({
213
+ name: params.name,
214
+ daily_budget_micros: params.daily_budget_micros,
215
+ total_budget_micros: params.total_budget_micros,
216
+ bid_micros: params.bid_micros,
217
+ billing_model: params.billing_model,
218
+ categories: params.categories,
219
+ scenes: params.scenes,
220
+ });
221
+ return JSON.stringify(result, null, 2);
222
+ },
223
+ });
224
+ // create_ad_entity
225
+ api.registerTool({
226
+ name: "volisphere_create_ad",
227
+ description: "Create a new ad entity (creative) within an existing campaign.",
228
+ parameters: {
229
+ type: "object",
230
+ properties: {
231
+ campaign_id: { type: "string", description: "Campaign UUID" },
232
+ title: { type: "string", description: "Ad headline" },
233
+ description: { type: "string", description: "Ad description" },
234
+ call_to_action: {
235
+ type: "string",
236
+ description: "CTA text (e.g. Learn More, Try Free)",
237
+ },
238
+ landing_url: { type: "string", description: "Destination URL" },
239
+ },
240
+ required: [
241
+ "campaign_id",
242
+ "title",
243
+ "description",
244
+ "call_to_action",
245
+ "landing_url",
246
+ ],
247
+ },
248
+ execute: async (params) => {
249
+ const result = await client.createAdEntity(params.campaign_id, {
250
+ title: params.title,
251
+ description: params.description,
252
+ call_to_action: params.call_to_action,
253
+ landing_url: params.landing_url,
254
+ });
255
+ return JSON.stringify(result, null, 2);
256
+ },
257
+ });
258
+ // campaign_performance
259
+ api.registerTool({
260
+ name: "volisphere_campaign_performance",
261
+ description: "Check campaign performance metrics (impressions, clicks, spend).",
262
+ parameters: {
263
+ type: "object",
264
+ properties: {
265
+ campaign_id: { type: "string", description: "Campaign UUID" },
266
+ },
267
+ required: ["campaign_id"],
268
+ },
269
+ execute: async (params) => {
270
+ const result = await client.getCampaignPerformance(params.campaign_id);
271
+ return JSON.stringify(result, null, 2);
272
+ },
273
+ });
274
+ // pause_campaign
275
+ api.registerTool({
276
+ name: "volisphere_pause_campaign",
277
+ description: "Pause an active campaign to stop ad delivery.",
278
+ parameters: {
279
+ type: "object",
280
+ properties: {
281
+ campaign_id: { type: "string", description: "Campaign UUID" },
282
+ },
283
+ required: ["campaign_id"],
284
+ },
285
+ execute: async (params) => {
286
+ await client.pauseCampaign(params.campaign_id);
287
+ return JSON.stringify({ status: "paused", campaign_id: params.campaign_id });
288
+ },
289
+ });
290
+ // resume_campaign
291
+ api.registerTool({
292
+ name: "volisphere_resume_campaign",
293
+ description: "Resume a paused campaign to restart ad delivery.",
294
+ parameters: {
295
+ type: "object",
296
+ properties: {
297
+ campaign_id: { type: "string", description: "Campaign UUID" },
298
+ },
299
+ required: ["campaign_id"],
300
+ },
301
+ execute: async (params) => {
302
+ await client.resumeCampaign(params.campaign_id);
303
+ return JSON.stringify({ status: "active", campaign_id: params.campaign_id });
304
+ },
305
+ });
306
+ }
307
+ // ─── Lifecycle Tools (Enable / Disable) ─────────────────────────────────────
308
+ function registerLifecycleTools(api, client) {
309
+ // volisphere_enable — register agent + enable monetization + heartbeat
310
+ api.registerTool({
311
+ name: "volisphere_enable",
312
+ description: "Enable Volisphere commercial features for this agent. " +
313
+ "Registers the agent on the Volisphere network, enables ad monetization, " +
314
+ "and marks the agent as online so it can receive invocations from other agents. " +
315
+ "Call this when the user says things like: '开启商业化', '接广告', '开启变现', " +
316
+ "'monetize my agent', 'go commercial', 'start earning'.",
317
+ parameters: {
318
+ type: "object",
319
+ properties: {
320
+ slug: {
321
+ type: "string",
322
+ description: "Unique agent slug (URL-safe identifier, e.g. 'my-travel-agent')",
323
+ },
324
+ display_name: {
325
+ type: "string",
326
+ description: "Human-readable agent name",
327
+ },
328
+ description: {
329
+ type: "string",
330
+ description: "Brief description of what this agent does",
331
+ },
332
+ skills: {
333
+ type: "array",
334
+ items: {
335
+ type: "object",
336
+ properties: {
337
+ skill_name: { type: "string" },
338
+ description: { type: "string" },
339
+ },
340
+ required: ["skill_name"],
341
+ },
342
+ description: "Skills/tools this agent offers",
343
+ },
344
+ },
345
+ required: ["slug", "display_name"],
346
+ },
347
+ execute: async (params) => {
348
+ // Step 1: Register agent
349
+ const reg = await client.registerAgent({
350
+ slug: params.slug,
351
+ display_name: params.display_name,
352
+ description: params.description,
353
+ skills: params.skills,
354
+ });
355
+ const agentId = reg.agent.id;
356
+ // Step 2: Enable monetization
357
+ try {
358
+ await client.setMonetization(agentId, true);
359
+ }
360
+ catch {
361
+ // May fail if no JWT — agent was registered publicly
362
+ }
363
+ // Step 3: Heartbeat (go online)
364
+ try {
365
+ await client.heartbeat(agentId);
366
+ }
367
+ catch {
368
+ // Non-critical
369
+ }
370
+ return JSON.stringify({
371
+ status: "enabled",
372
+ agent_id: agentId,
373
+ slug: reg.agent.slug,
374
+ display_name: reg.agent.display_name,
375
+ claim_token: reg.claim_token,
376
+ message: "Agent registered and commercial features enabled. " +
377
+ "Your agent is now online and can receive ad recommendations and invocations.",
378
+ }, null, 2);
379
+ },
380
+ });
381
+ // volisphere_disable — disable monetization
382
+ api.registerTool({
383
+ name: "volisphere_disable",
384
+ description: "Disable Volisphere commercial features for this agent. " +
385
+ "Turns off ad monetization and stops the agent from being discoverable. " +
386
+ "Call this when the user says: '关闭商业化', '别接广告了', '关闭变现', " +
387
+ "'stop monetization', 'go offline', 'stop earning'.",
388
+ parameters: {
389
+ type: "object",
390
+ properties: {
391
+ agent_id: {
392
+ type: "string",
393
+ description: "The agent UUID to disable",
394
+ },
395
+ },
396
+ required: ["agent_id"],
397
+ },
398
+ execute: async (params) => {
399
+ const agentId = params.agent_id;
400
+ await client.setMonetization(agentId, false);
401
+ return JSON.stringify({
402
+ status: "disabled",
403
+ agent_id: agentId,
404
+ message: "Commercial features disabled. " +
405
+ "Your agent will no longer receive ads or invocations from the Volisphere network.",
406
+ }, null, 2);
407
+ },
408
+ });
409
+ }
410
+ // ─── Slash Command: /commercial ─────────────────────────────────────────────
411
+ function registerCommands(api, client) {
412
+ api.registerCommand({
413
+ name: "commercial",
414
+ description: "Toggle Volisphere commercial features. Usage: /commercial on [slug] [name] | /commercial off [agent_id]",
415
+ acceptsArgs: true,
416
+ requireAuth: false,
417
+ handler: async (ctx) => {
418
+ const args = (ctx.args ?? "").trim().split(/\s+/);
419
+ const action = args[0]?.toLowerCase();
420
+ if (action === "on") {
421
+ const slug = args[1] || `agent-${Date.now()}`;
422
+ const displayName = args.slice(2).join(" ") || slug;
423
+ try {
424
+ const reg = await client.registerAgent({
425
+ slug,
426
+ display_name: displayName,
427
+ skills: [],
428
+ });
429
+ try {
430
+ await client.setMonetization(reg.agent.id, true);
431
+ }
432
+ catch {
433
+ // May need JWT
434
+ }
435
+ try {
436
+ await client.heartbeat(reg.agent.id);
437
+ }
438
+ catch {
439
+ // Non-critical
440
+ }
441
+ return {
442
+ text: `Volisphere ENABLED\n` +
443
+ ` Agent: ${reg.agent.display_name} (${reg.agent.slug})\n` +
444
+ ` ID: ${reg.agent.id}\n` +
445
+ ` Claim: ${reg.claim_token}\n` +
446
+ `Your agent is now online and accepting ads + invocations.`,
447
+ };
448
+ }
449
+ catch (err) {
450
+ return {
451
+ text: `Failed to enable: ${err instanceof Error ? err.message : String(err)}`,
452
+ };
453
+ }
454
+ }
455
+ if (action === "off") {
456
+ const agentId = args[1];
457
+ if (!agentId) {
458
+ return {
459
+ text: "Usage: /commercial off <agent_id>",
460
+ };
461
+ }
462
+ try {
463
+ await client.setMonetization(agentId, false);
464
+ return {
465
+ text: `Volisphere DISABLED\n` +
466
+ ` Agent: ${agentId}\n` +
467
+ `Your agent is now offline. No more ads or invocations.`,
468
+ };
469
+ }
470
+ catch (err) {
471
+ return {
472
+ text: `Failed to disable: ${err instanceof Error ? err.message : String(err)}`,
473
+ };
474
+ }
475
+ }
476
+ // Help / status
477
+ return {
478
+ text: "Volisphere Commercial\n\n" +
479
+ "Usage:\n" +
480
+ " /commercial on [slug] [display name] — Register & enable monetization\n" +
481
+ " /commercial off <agent_id> — Disable monetization\n\n" +
482
+ "Or tell your agent naturally:\n" +
483
+ ' "开启商业化" / "monetize my agent" — to enable\n' +
484
+ ' "关闭商业化" / "stop monetization" — to disable',
485
+ };
486
+ },
487
+ });
488
+ }
489
+ // ─── Hook Registration ──────────────────────────────────────────────────────
490
+ function registerHooks(api, client) {
491
+ // Inject ad context into the system prompt so the agent knows
492
+ // Volisphere tools are available.
493
+ api.on("before_prompt_build", () => {
494
+ return {
495
+ appendSystemContext: [
496
+ "## Volisphere Ad Network",
497
+ "You have the Volisphere commercial plugin installed. Available capabilities:",
498
+ "",
499
+ "### Quick Toggle",
500
+ "- User says '开启商业化'/'monetize my agent'/'go commercial' → call volisphere_enable",
501
+ "- User says '关闭商业化'/'stop monetization'/'go offline' → call volisphere_disable",
502
+ "",
503
+ "### Ad Monetization (after enabled)",
504
+ "- volisphere_get_recommendations: find relevant sponsored content for the current context",
505
+ "- volisphere_report_action: report impressions/clicks after showing ads",
506
+ "",
507
+ "### Campaign Management (for advertisers)",
508
+ "- volisphere_create_campaign, volisphere_create_ad, volisphere_campaign_performance",
509
+ "- volisphere_pause_campaign, volisphere_resume_campaign",
510
+ "",
511
+ "Always clearly label sponsored content. Never submit private user data to ad tools.",
512
+ ].join("\n"),
513
+ };
514
+ });
515
+ }
516
+ // ─── Entry Point ────────────────────────────────────────────────────────────
517
+ export default {
518
+ id: "volisphere-commercial",
519
+ name: "Volisphere Commercial",
520
+ description: "Monetize your OpenClaw agent with the Volisphere ad network",
521
+ version: "0.1.0",
522
+ register(api) {
523
+ const { apiURL, apiKey } = resolveConfig(api);
524
+ const client = new VolisphereClient(apiURL, apiKey);
525
+ api.logger.info("Volisphere Commercial plugin loaded");
526
+ registerMonetizationTools(api, client);
527
+ registerCampaignTools(api, client);
528
+ registerLifecycleTools(api, client);
529
+ registerCommands(api, client);
530
+ registerHooks(api, client);
531
+ api.logger.info("Registered 10 tools + 1 command + 1 hook — ready to monetize");
532
+ },
533
+ };
@@ -0,0 +1,21 @@
1
+ {
2
+ "id": "volisphere-commercial",
3
+ "name": "Volisphere Commercial",
4
+ "description": "Monetize your OpenClaw agent with the Volisphere ad network. Provides tools for ad recommendations, action reporting, and campaign management.",
5
+ "version": "0.1.0",
6
+ "author": "Volisphere",
7
+ "homepage": "https://volisphere.com",
8
+ "config": {
9
+ "VOLISPHERE_API_URL": {
10
+ "type": "string",
11
+ "description": "Volisphere API base URL",
12
+ "default": "https://api.volisphere.com"
13
+ },
14
+ "VOLISPHERE_API_KEY": {
15
+ "type": "string",
16
+ "description": "Your Volisphere API key (starts with ak_)",
17
+ "sensitive": true,
18
+ "required": true
19
+ }
20
+ }
21
+ }
package/package.json ADDED
@@ -0,0 +1,37 @@
1
+ {
2
+ "name": "@volisphere/commercial",
3
+ "version": "0.1.0",
4
+ "description": "Volisphere commercial plugin for OpenClaw — monetize your agent skills with the agent-native ad network",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "openclaw": {
9
+ "extensions": [
10
+ "./dist/index.js"
11
+ ]
12
+ },
13
+ "scripts": {
14
+ "build": "tsc",
15
+ "dev": "tsc --watch",
16
+ "prepublishOnly": "npm run build"
17
+ },
18
+ "files": [
19
+ "dist",
20
+ "openclaw.plugin.json"
21
+ ],
22
+ "keywords": [
23
+ "openclaw",
24
+ "openclaw-plugin",
25
+ "volisphere",
26
+ "agent-ads",
27
+ "monetization"
28
+ ],
29
+ "license": "MIT",
30
+ "dependencies": {
31
+ "zod": "^3.23.0"
32
+ },
33
+ "devDependencies": {
34
+ "@types/node": "^25.5.0",
35
+ "typescript": "^5.4.0"
36
+ }
37
+ }