@kanvas/openclaw-plugin 0.1.11 → 0.1.12

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.
Files changed (2) hide show
  1. package/dist/index.js +39 -30
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -10,6 +10,18 @@ import { registerOrdersTools } from "./tools/orders.js";
10
10
  import { registerSocialTools } from "./tools/social.js";
11
11
  import { toolResult } from "./tools/helpers.js";
12
12
  const DEFAULT_API_URL = "https://graphapi.kanvas.dev/graphql";
13
+ // OpenClaw v2026.4.5+ calls register() per-agent-context (main, subagents,
14
+ // cron lanes). Heavy objects (client, services) are created once and shared;
15
+ // tools & hooks must be registered on every api object.
16
+ let sharedClient = null;
17
+ let sharedConfig = null;
18
+ let sharedEnsureAuth = null;
19
+ let sharedCrm = null;
20
+ let sharedInventory = null;
21
+ let sharedOrders = null;
22
+ let sharedSocial = null;
23
+ let startupBannerShown = false;
24
+ let skipBannerShown = false;
13
25
  function resolveConfig(pluginConfig) {
14
26
  const cfg = pluginConfig ?? {};
15
27
  const apiUrl = cfg.apiUrl || process.env.KANVAS_API_URL || DEFAULT_API_URL;
@@ -67,38 +79,35 @@ export default {
67
79
  description: "Connects agents to Kanvas — your company's nervous system for CRM, inventory, orders, and messaging.",
68
80
  configSchema: { type: "object" },
69
81
  register(api) {
70
- // Guard: resolve config and log a warning instead of throwing if
71
- // credentials are missing. This prevents the gateway from entering
72
- // an infinite retry loop when the plugin is installed but not yet
73
- // configured, or when the gateway re-invokes register() multiple times.
82
+ // Resolve config log once and bail silently on missing credentials.
74
83
  let config;
75
84
  try {
76
85
  config = resolveConfig(api.pluginConfig);
77
86
  }
78
87
  catch (err) {
79
- api.logger.info(`Kanvas plugin skipped: ${err.message}. Run "openclaw kanvas setup" to configure.`);
80
- // Still register the CLI so the user can run setup even without config
81
- api.registerCli((ctx) => {
82
- ctx.program
83
- .command("setup")
84
- .description("Interactive setup — configure Kanvas credentials and test the connection")
85
- .action(async () => {
86
- const { runSetup } = await import("./cli/setup.js");
87
- await runSetup();
88
- });
89
- }, { commands: ["setup"] });
88
+ if (!skipBannerShown) {
89
+ api.logger.info(`Kanvas plugin skipped: ${err.message}. Run "openclaw kanvas setup" to configure.`);
90
+ skipBannerShown = true;
91
+ }
90
92
  return;
91
93
  }
92
- const client = new KanvasClient(config);
93
- const ensureAuth = createAuthGuard(client, config, api.logger);
94
- const crm = new CrmService(client);
95
- const inventory = new InventoryService(client);
96
- const orders = new OrdersService(client);
97
- const social = new SocialService(client);
98
- registerCrmTools(api, crm, ensureAuth);
99
- registerInventoryTools(api, inventory, ensureAuth);
100
- registerOrdersTools(api, orders, ensureAuth);
101
- registerSocialTools(api, social, ensureAuth);
94
+ // Create heavy objects once; reuse across agent contexts.
95
+ if (!sharedClient) {
96
+ sharedConfig = config;
97
+ sharedClient = new KanvasClient(config);
98
+ sharedEnsureAuth = createAuthGuard(sharedClient, config, api.logger);
99
+ sharedCrm = new CrmService(sharedClient);
100
+ sharedInventory = new InventoryService(sharedClient);
101
+ sharedOrders = new OrdersService(sharedClient);
102
+ sharedSocial = new SocialService(sharedClient);
103
+ }
104
+ // Tools and hooks must be registered on every api object — each one is
105
+ // a separate agent context (main, subagents, cron lanes).
106
+ const ensureAuth = sharedEnsureAuth;
107
+ registerCrmTools(api, sharedCrm, ensureAuth);
108
+ registerInventoryTools(api, sharedInventory, ensureAuth);
109
+ registerOrdersTools(api, sharedOrders, ensureAuth);
110
+ registerSocialTools(api, sharedSocial, ensureAuth);
102
111
  api.registerTool({
103
112
  name: "kanvas_test_connection",
104
113
  label: "Test Connection",
@@ -106,15 +115,12 @@ export default {
106
115
  parameters: Type.Object({}),
107
116
  async execute() {
108
117
  await ensureAuth();
109
- return toolResult(await client.testConnection());
118
+ return toolResult(await sharedClient.testConnection());
110
119
  },
111
120
  });
112
- // Inject Kanvas context into the agent's system prompt so it knows
113
- // what these tools are for and how to use them together.
114
121
  api.on("before_prompt_build", () => ({
115
122
  appendSystemContext: KANVAS_SYSTEM_CONTEXT,
116
123
  }));
117
- // Register `openclaw kanvas setup` CLI command for interactive configuration.
118
124
  api.registerCli((ctx) => {
119
125
  ctx.program
120
126
  .command("setup")
@@ -124,7 +130,10 @@ export default {
124
130
  await runSetup();
125
131
  });
126
132
  }, { commands: ["setup"] });
127
- api.logger.info("Kanvas plugin registered — 53 tools loaded");
133
+ if (!startupBannerShown) {
134
+ startupBannerShown = true;
135
+ api.logger.info("Kanvas plugin registered — 53 tools loaded");
136
+ }
128
137
  },
129
138
  };
130
139
  const KANVAS_SYSTEM_CONTEXT = `
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kanvas/openclaw-plugin",
3
- "version": "0.1.11",
3
+ "version": "0.1.12",
4
4
  "description": "Connects agents to Kanvas — your company's nervous system for CRM, inventory, orders, and messaging.",
5
5
  "license": "MIT",
6
6
  "repository": {