@kanvas/openclaw-plugin 0.1.13 → 0.1.15

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.
@@ -396,7 +396,7 @@ export class CrmService {
396
396
  }
397
397
  async listLeadMessages(channelSlug, first = 50, page = 1) {
398
398
  const query = `
399
- query LeadMessages($first: Int, $page: Int, $channelSlug: String!) {
399
+ query LeadMessages($first: Int, $page: Int, $channelSlug: Mixed!) {
400
400
  messages(
401
401
  first: $first
402
402
  page: $page
@@ -635,9 +635,15 @@ export class CrmService {
635
635
  data {
636
636
  id
637
637
  name
638
+ slug
639
+ weight
640
+ is_default
641
+ description
638
642
  stages {
639
643
  id
640
644
  name
645
+ rotting_days
646
+ weight
641
647
  }
642
648
  }
643
649
  }
@@ -645,6 +651,92 @@ export class CrmService {
645
651
  `;
646
652
  return this.client.query(query, { first });
647
653
  }
654
+ async createPipeline(input) {
655
+ const mutation = `
656
+ mutation CreatePipeline($input: PipelineInput!) {
657
+ createPipeline(input: $input) {
658
+ id
659
+ name
660
+ slug
661
+ weight
662
+ is_default
663
+ description
664
+ stages {
665
+ id
666
+ name
667
+ rotting_days
668
+ weight
669
+ }
670
+ }
671
+ }
672
+ `;
673
+ return this.client.query(mutation, { input });
674
+ }
675
+ async updatePipeline(id, input) {
676
+ const mutation = `
677
+ mutation UpdatePipeline($id: ID!, $input: PipelineInput!) {
678
+ updatePipeline(id: $id, input: $input) {
679
+ id
680
+ name
681
+ slug
682
+ weight
683
+ is_default
684
+ description
685
+ stages {
686
+ id
687
+ name
688
+ rotting_days
689
+ weight
690
+ }
691
+ }
692
+ }
693
+ `;
694
+ return this.client.query(mutation, { id, input });
695
+ }
696
+ async deletePipeline(id) {
697
+ const mutation = `
698
+ mutation DeletePipeline($id: ID!) {
699
+ deletePipeline(id: $id)
700
+ }
701
+ `;
702
+ return this.client.query(mutation, { id });
703
+ }
704
+ async createPipelineStage(input) {
705
+ const mutation = `
706
+ mutation CreatePipelineStage($input: PipelineStageInput!) {
707
+ createPipelineStage(input: $input) {
708
+ id
709
+ name
710
+ rotting_days
711
+ weight
712
+ pipeline { id name }
713
+ }
714
+ }
715
+ `;
716
+ return this.client.query(mutation, { input });
717
+ }
718
+ async updatePipelineStage(id, input) {
719
+ const mutation = `
720
+ mutation UpdatePipelineStage($id: ID!, $input: PipelineStageInput!) {
721
+ updatePipelineStage(id: $id, input: $input) {
722
+ id
723
+ name
724
+ rotting_days
725
+ weight
726
+ pipeline { id name }
727
+ }
728
+ }
729
+ `;
730
+ return this.client.query(mutation, { id, input });
731
+ }
732
+ async deletePipelineStage(id) {
733
+ const mutation = `
734
+ mutation DeletePipelineStage($id: ID!) {
735
+ deletePipelineStage(id: $id)
736
+ }
737
+ `;
738
+ return this.client.query(mutation, { id });
739
+ }
648
740
  async attachFileToLeadByUrl(leadId, fileUrl, fileName) {
649
741
  const mutation = `
650
742
  mutation CreateFilesystem($input: FilesystemInputUrl!) {
@@ -33,12 +33,16 @@ export class SocialService {
33
33
  system_modules
34
34
  }
35
35
  tags {
36
- id
37
- name
36
+ data {
37
+ id
38
+ name
39
+ }
38
40
  }
39
41
  custom_fields {
40
- name
41
- value
42
+ data {
43
+ name
44
+ value
45
+ }
42
46
  }
43
47
  }
44
48
  }
@@ -68,7 +72,6 @@ export class SocialService {
68
72
  is_public
69
73
  is_locked
70
74
  created_at
71
- updated_at
72
75
  parent {
73
76
  id
74
77
  uuid
@@ -118,12 +121,16 @@ export class SocialService {
118
121
  }
119
122
  }
120
123
  tags {
121
- id
122
- name
124
+ data {
125
+ id
126
+ name
127
+ }
123
128
  }
124
129
  custom_fields {
125
- name
126
- value
130
+ data {
131
+ name
132
+ value
133
+ }
127
134
  }
128
135
  }
129
136
  }
@@ -143,19 +150,22 @@ export class SocialService {
143
150
  message
144
151
  is_public
145
152
  is_locked
146
- updated_at
147
153
  messageType {
148
154
  id
149
155
  name
150
156
  verb
151
157
  }
152
158
  tags {
153
- id
154
- name
159
+ data {
160
+ id
161
+ name
162
+ }
155
163
  }
156
164
  custom_fields {
157
- name
158
- value
165
+ data {
166
+ name
167
+ value
168
+ }
159
169
  }
160
170
  }
161
171
  }
@@ -219,8 +229,10 @@ export class SocialService {
219
229
  }
220
230
  }
221
231
  tags {
222
- id
223
- name
232
+ data {
233
+ id
234
+ name
235
+ }
224
236
  }
225
237
  }
226
238
  paginatorInfo {
@@ -286,8 +298,10 @@ export class SocialService {
286
298
  system_modules
287
299
  }
288
300
  tags {
289
- id
290
- name
301
+ data {
302
+ id
303
+ name
304
+ }
291
305
  }
292
306
  }
293
307
  paginatorInfo {
package/dist/tools/crm.js CHANGED
@@ -304,6 +304,109 @@ export function registerCrmTools(api, service, ensureAuth) {
304
304
  return toolResult(await service.listPipelines(params.first));
305
305
  },
306
306
  });
307
+ // --- Pipeline Management ---
308
+ api.registerTool({
309
+ name: "kanvas_create_pipeline",
310
+ label: "Create Pipeline",
311
+ description: "Create a new lead pipeline. Optionally include stages in one call. " +
312
+ "Weight controls display order (lower = first). is_default marks the pipeline used for new leads.",
313
+ parameters: Type.Object({
314
+ name: Type.String({ description: "Pipeline name" }),
315
+ weight: Type.Number({ description: "Sort order (lower = first)" }),
316
+ is_default: Type.Boolean({ description: "Whether this is the default pipeline for new leads" }),
317
+ description: Type.Optional(Type.String({ description: "Pipeline description" })),
318
+ slug: Type.Optional(Type.String({ description: "URL-friendly slug (auto-generated from name if omitted)" })),
319
+ stages: Type.Optional(Type.Array(Type.Object({
320
+ name: Type.String({ description: "Stage name" }),
321
+ rotting_days: Type.Number({ description: "Days before a lead in this stage is considered stale (0 = no rotting)" }),
322
+ weight: Type.Number({ description: "Sort order within pipeline (lower = first)" }),
323
+ }), { description: "Initial stages to create with the pipeline" })),
324
+ }),
325
+ async execute(_id, params) {
326
+ await ensureAuth();
327
+ return toolResult(await service.createPipeline(params));
328
+ },
329
+ });
330
+ api.registerTool({
331
+ name: "kanvas_update_pipeline",
332
+ label: "Update Pipeline",
333
+ description: "Update an existing pipeline's name, weight, default status, or stages. " +
334
+ "To update existing stages, include stages_id in each stage object.",
335
+ parameters: Type.Object({
336
+ id: Type.String({ description: "Pipeline ID" }),
337
+ name: Type.String({ description: "Pipeline name" }),
338
+ weight: Type.Number({ description: "Sort order" }),
339
+ is_default: Type.Boolean({ description: "Whether this is the default pipeline" }),
340
+ description: Type.Optional(Type.String({ description: "Pipeline description" })),
341
+ slug: Type.Optional(Type.String({ description: "URL-friendly slug" })),
342
+ stages: Type.Optional(Type.Array(Type.Object({
343
+ name: Type.String({ description: "Stage name" }),
344
+ rotting_days: Type.Number({ description: "Days before rotting (0 = disabled)" }),
345
+ weight: Type.Number({ description: "Sort order within pipeline" }),
346
+ stages_id: Type.Optional(Type.String({ description: "Existing stage ID to update (omit to create new)" })),
347
+ }))),
348
+ }),
349
+ async execute(_id, params) {
350
+ await ensureAuth();
351
+ const { id, ...input } = params;
352
+ return toolResult(await service.updatePipeline(id, input));
353
+ },
354
+ });
355
+ api.registerTool({
356
+ name: "kanvas_delete_pipeline",
357
+ label: "Delete Pipeline",
358
+ description: "Delete a pipeline. Will fail if the pipeline still has leads assigned to it.",
359
+ parameters: Type.Object({
360
+ id: Type.String({ description: "Pipeline ID" }),
361
+ }),
362
+ async execute(_id, params) {
363
+ await ensureAuth();
364
+ return toolResult(await service.deletePipeline(params.id));
365
+ },
366
+ });
367
+ api.registerTool({
368
+ name: "kanvas_create_pipeline_stage",
369
+ label: "Create Pipeline Stage",
370
+ description: "Add a new stage to an existing pipeline.",
371
+ parameters: Type.Object({
372
+ pipeline_id: Type.String({ description: "Pipeline ID to add the stage to" }),
373
+ name: Type.String({ description: "Stage name" }),
374
+ rotting_days: Type.Number({ description: "Days before a lead in this stage is considered stale (0 = no rotting)" }),
375
+ weight: Type.Number({ description: "Sort order within pipeline (lower = first)" }),
376
+ }),
377
+ async execute(_id, params) {
378
+ await ensureAuth();
379
+ return toolResult(await service.createPipelineStage(params));
380
+ },
381
+ });
382
+ api.registerTool({
383
+ name: "kanvas_update_pipeline_stage",
384
+ label: "Update Pipeline Stage",
385
+ description: "Update an existing pipeline stage's name, rotting days, or weight.",
386
+ parameters: Type.Object({
387
+ id: Type.String({ description: "Stage ID" }),
388
+ name: Type.String({ description: "Stage name" }),
389
+ rotting_days: Type.Number({ description: "Days before rotting (0 = disabled)" }),
390
+ weight: Type.Number({ description: "Sort order within pipeline" }),
391
+ }),
392
+ async execute(_id, params) {
393
+ await ensureAuth();
394
+ const { id, ...input } = params;
395
+ return toolResult(await service.updatePipelineStage(id, input));
396
+ },
397
+ });
398
+ api.registerTool({
399
+ name: "kanvas_delete_pipeline_stage",
400
+ label: "Delete Pipeline Stage",
401
+ description: "Delete a stage from a pipeline. Will fail if leads are currently in this stage.",
402
+ parameters: Type.Object({
403
+ id: Type.String({ description: "Stage ID" }),
404
+ }),
405
+ async execute(_id, params) {
406
+ await ensureAuth();
407
+ return toolResult(await service.deletePipelineStage(params.id));
408
+ },
409
+ });
307
410
  api.registerTool({
308
411
  name: "kanvas_list_lead_statuses",
309
412
  label: "List Lead Statuses",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kanvas/openclaw-plugin",
3
- "version": "0.1.13",
3
+ "version": "0.1.15",
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": {
@@ -32,7 +32,9 @@
32
32
  "prepublishOnly": "npm run build",
33
33
  "build": "tsc -p tsconfig.json",
34
34
  "check": "tsc --noEmit -p tsconfig.json",
35
- "dev": "node --watch --loader ts-node/esm src/index.ts"
35
+ "dev": "node --watch --loader ts-node/esm src/index.ts",
36
+ "test": "vitest run",
37
+ "test:watch": "vitest"
36
38
  },
37
39
  "engines": {
38
40
  "node": ">=20"
@@ -45,8 +47,10 @@
45
47
  },
46
48
  "devDependencies": {
47
49
  "@types/node": "^24.5.2",
50
+ "dotenv": "^17.4.1",
48
51
  "openclaw": "^2026.3.24",
49
52
  "ts-node": "^10.9.2",
50
- "typescript": "^5.9.2"
53
+ "typescript": "^5.9.2",
54
+ "vitest": "^4.1.4"
51
55
  }
52
56
  }