@kanvas/openclaw-plugin 0.1.11 → 0.1.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/index.js +53 -33
- 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,46 @@ 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
|
-
//
|
|
71
|
-
//
|
|
72
|
-
//
|
|
73
|
-
//
|
|
74
|
-
|
|
82
|
+
// Resolve plugin config. api.pluginConfig is set on the gateway init
|
|
83
|
+
// context but often undefined on agent contexts (Slack, subagents, cron).
|
|
84
|
+
// Fall back to extracting from the full app config (api.config), which
|
|
85
|
+
// is always available — matching the pattern used by budget-guard and
|
|
86
|
+
// lossless-claw.
|
|
87
|
+
const pluginCfg = api.pluginConfig
|
|
88
|
+
?? api.config?.plugins?.entries?.kanvas?.config
|
|
89
|
+
?? {};
|
|
90
|
+
let config = null;
|
|
75
91
|
try {
|
|
76
|
-
config = resolveConfig(
|
|
92
|
+
config = resolveConfig(pluginCfg);
|
|
77
93
|
}
|
|
78
94
|
catch (err) {
|
|
79
|
-
|
|
80
|
-
//
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
.
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
});
|
|
89
|
-
}, { commands: ["setup"] });
|
|
90
|
-
return;
|
|
95
|
+
// If shared state exists from a prior init, fall through to register
|
|
96
|
+
// tools. Otherwise this is genuinely unconfigured — bail.
|
|
97
|
+
if (!sharedClient) {
|
|
98
|
+
if (!skipBannerShown) {
|
|
99
|
+
api.logger.info(`Kanvas plugin skipped: ${err.message}. Run "openclaw kanvas setup" to configure.`);
|
|
100
|
+
skipBannerShown = true;
|
|
101
|
+
}
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
91
104
|
}
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
105
|
+
// Create heavy objects once; reuse across agent contexts.
|
|
106
|
+
if (!sharedClient && config) {
|
|
107
|
+
sharedConfig = config;
|
|
108
|
+
sharedClient = new KanvasClient(config);
|
|
109
|
+
sharedEnsureAuth = createAuthGuard(sharedClient, config, api.logger);
|
|
110
|
+
sharedCrm = new CrmService(sharedClient);
|
|
111
|
+
sharedInventory = new InventoryService(sharedClient);
|
|
112
|
+
sharedOrders = new OrdersService(sharedClient);
|
|
113
|
+
sharedSocial = new SocialService(sharedClient);
|
|
114
|
+
}
|
|
115
|
+
// Tools and hooks must be registered on every api object — each one is
|
|
116
|
+
// a separate agent context (main, subagents, cron lanes).
|
|
117
|
+
const ensureAuth = sharedEnsureAuth;
|
|
118
|
+
registerCrmTools(api, sharedCrm, ensureAuth);
|
|
119
|
+
registerInventoryTools(api, sharedInventory, ensureAuth);
|
|
120
|
+
registerOrdersTools(api, sharedOrders, ensureAuth);
|
|
121
|
+
registerSocialTools(api, sharedSocial, ensureAuth);
|
|
102
122
|
api.registerTool({
|
|
103
123
|
name: "kanvas_test_connection",
|
|
104
124
|
label: "Test Connection",
|
|
@@ -106,15 +126,12 @@ export default {
|
|
|
106
126
|
parameters: Type.Object({}),
|
|
107
127
|
async execute() {
|
|
108
128
|
await ensureAuth();
|
|
109
|
-
return toolResult(await
|
|
129
|
+
return toolResult(await sharedClient.testConnection());
|
|
110
130
|
},
|
|
111
131
|
});
|
|
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
132
|
api.on("before_prompt_build", () => ({
|
|
115
133
|
appendSystemContext: KANVAS_SYSTEM_CONTEXT,
|
|
116
134
|
}));
|
|
117
|
-
// Register `openclaw kanvas setup` CLI command for interactive configuration.
|
|
118
135
|
api.registerCli((ctx) => {
|
|
119
136
|
ctx.program
|
|
120
137
|
.command("setup")
|
|
@@ -124,7 +141,10 @@ export default {
|
|
|
124
141
|
await runSetup();
|
|
125
142
|
});
|
|
126
143
|
}, { commands: ["setup"] });
|
|
127
|
-
|
|
144
|
+
if (!startupBannerShown) {
|
|
145
|
+
startupBannerShown = true;
|
|
146
|
+
api.logger.info("Kanvas plugin registered — 53 tools loaded");
|
|
147
|
+
}
|
|
128
148
|
},
|
|
129
149
|
};
|
|
130
150
|
const KANVAS_SYSTEM_CONTEXT = `
|
package/package.json
CHANGED