@kanvas/openclaw-plugin 0.1.15 → 0.1.17
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/domains/deals/index.js +103 -0
- package/dist/domains/deals/types.js +1 -0
- package/dist/domains/ecosystem/index.js +167 -0
- package/dist/domains/events/index.js +157 -0
- package/dist/domains/events/types.js +1 -0
- package/dist/domains/orders/index.js +145 -0
- package/dist/domains/orders/types.js +1 -0
- package/dist/index.js +56 -1
- package/dist/tools/deals.js +91 -0
- package/dist/tools/ecosystem.js +145 -0
- package/dist/tools/events.js +134 -0
- package/dist/tools/orders.js +185 -0
- package/package.json +1 -1
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
export class DealsService {
|
|
2
|
+
client;
|
|
3
|
+
constructor(client) {
|
|
4
|
+
this.client = client;
|
|
5
|
+
}
|
|
6
|
+
async listDeals(first = 25, search, where) {
|
|
7
|
+
const query = `
|
|
8
|
+
query ListDeals($first: Int, $search: String, $where: QueryDealsWhereWhereConditions) {
|
|
9
|
+
deals(first: $first, search: $search, where: $where) {
|
|
10
|
+
data {
|
|
11
|
+
id
|
|
12
|
+
uuid
|
|
13
|
+
title
|
|
14
|
+
description
|
|
15
|
+
created_at
|
|
16
|
+
updated_at
|
|
17
|
+
owner { id uuid displayname }
|
|
18
|
+
lead { id uuid }
|
|
19
|
+
people { id uuid firstname lastname }
|
|
20
|
+
organization { id name }
|
|
21
|
+
pipeline { id name }
|
|
22
|
+
stage { id name }
|
|
23
|
+
status { id name }
|
|
24
|
+
}
|
|
25
|
+
paginatorInfo {
|
|
26
|
+
currentPage
|
|
27
|
+
lastPage
|
|
28
|
+
total
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
`;
|
|
33
|
+
return this.client.query(query, { first, search, where });
|
|
34
|
+
}
|
|
35
|
+
async getDeal(id) {
|
|
36
|
+
const query = `
|
|
37
|
+
query GetDeal($id: ID!) {
|
|
38
|
+
deal(id: $id) {
|
|
39
|
+
id
|
|
40
|
+
uuid
|
|
41
|
+
title
|
|
42
|
+
description
|
|
43
|
+
created_at
|
|
44
|
+
updated_at
|
|
45
|
+
owner { id uuid displayname }
|
|
46
|
+
lead { id uuid }
|
|
47
|
+
people { id uuid firstname lastname }
|
|
48
|
+
organization { id name }
|
|
49
|
+
pipeline { id name }
|
|
50
|
+
stage { id name }
|
|
51
|
+
status { id name }
|
|
52
|
+
tags { id name }
|
|
53
|
+
custom_fields { name value }
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
`;
|
|
57
|
+
return this.client.query(query, { id });
|
|
58
|
+
}
|
|
59
|
+
async createDeal(input) {
|
|
60
|
+
const mutation = `
|
|
61
|
+
mutation CreateDeal($input: DealInput!) {
|
|
62
|
+
createDeal(input: $input) {
|
|
63
|
+
id
|
|
64
|
+
uuid
|
|
65
|
+
title
|
|
66
|
+
description
|
|
67
|
+
created_at
|
|
68
|
+
owner { id uuid displayname }
|
|
69
|
+
pipeline { id name }
|
|
70
|
+
stage { id name }
|
|
71
|
+
status { id name }
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
`;
|
|
75
|
+
return this.client.query(mutation, { input });
|
|
76
|
+
}
|
|
77
|
+
async updateDeal(id, input) {
|
|
78
|
+
const mutation = `
|
|
79
|
+
mutation UpdateDeal($id: ID!, $input: UpdateDealInput!) {
|
|
80
|
+
updateDeal(id: $id, input: $input) {
|
|
81
|
+
id
|
|
82
|
+
uuid
|
|
83
|
+
title
|
|
84
|
+
description
|
|
85
|
+
updated_at
|
|
86
|
+
owner { id uuid displayname }
|
|
87
|
+
pipeline { id name }
|
|
88
|
+
stage { id name }
|
|
89
|
+
status { id name }
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
`;
|
|
93
|
+
return this.client.query(mutation, { id, input });
|
|
94
|
+
}
|
|
95
|
+
async deleteDeal(id) {
|
|
96
|
+
const mutation = `
|
|
97
|
+
mutation DeleteDeal($id: ID!) {
|
|
98
|
+
deleteDeal(id: $id)
|
|
99
|
+
}
|
|
100
|
+
`;
|
|
101
|
+
return this.client.query(mutation, { id });
|
|
102
|
+
}
|
|
103
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
export class EcosystemService {
|
|
2
|
+
client;
|
|
3
|
+
constructor(client) {
|
|
4
|
+
this.client = client;
|
|
5
|
+
}
|
|
6
|
+
// ── Companies ──────────────────────────────────────────────
|
|
7
|
+
async listCompanies(first = 25, search, where) {
|
|
8
|
+
const query = `
|
|
9
|
+
query ListCompanies($first: Int, $search: String, $where: QueryCompaniesWhereWhereConditions) {
|
|
10
|
+
companies(first: $first, search: $search, where: $where) {
|
|
11
|
+
data {
|
|
12
|
+
id
|
|
13
|
+
uuid
|
|
14
|
+
name
|
|
15
|
+
website
|
|
16
|
+
email
|
|
17
|
+
phone
|
|
18
|
+
address
|
|
19
|
+
city
|
|
20
|
+
state
|
|
21
|
+
country
|
|
22
|
+
zip
|
|
23
|
+
is_active
|
|
24
|
+
total_users
|
|
25
|
+
total_branches
|
|
26
|
+
created_at
|
|
27
|
+
}
|
|
28
|
+
paginatorInfo {
|
|
29
|
+
currentPage
|
|
30
|
+
lastPage
|
|
31
|
+
total
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
`;
|
|
36
|
+
return this.client.query(query, { first, search, where });
|
|
37
|
+
}
|
|
38
|
+
// ── Branches ───────────────────────────────────────────────
|
|
39
|
+
async listBranches(first = 25, search, where) {
|
|
40
|
+
const query = `
|
|
41
|
+
query ListBranches($first: Int, $search: String, $where: QueryBranchesWhereWhereConditions) {
|
|
42
|
+
branches(first: $first, search: $search, where: $where) {
|
|
43
|
+
data {
|
|
44
|
+
id
|
|
45
|
+
uuid
|
|
46
|
+
name
|
|
47
|
+
companies_id
|
|
48
|
+
email
|
|
49
|
+
phone
|
|
50
|
+
address
|
|
51
|
+
city
|
|
52
|
+
state
|
|
53
|
+
country
|
|
54
|
+
zip
|
|
55
|
+
is_default
|
|
56
|
+
is_active
|
|
57
|
+
total_users
|
|
58
|
+
created_at
|
|
59
|
+
}
|
|
60
|
+
paginatorInfo {
|
|
61
|
+
currentPage
|
|
62
|
+
lastPage
|
|
63
|
+
total
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
`;
|
|
68
|
+
return this.client.query(query, { first, search, where });
|
|
69
|
+
}
|
|
70
|
+
// ── Roles ──────────────────────────────────────────────────
|
|
71
|
+
async listRoles(first = 50, search) {
|
|
72
|
+
const query = `
|
|
73
|
+
query ListRoles($first: Int, $search: String) {
|
|
74
|
+
roles(first: $first, search: $search) {
|
|
75
|
+
data {
|
|
76
|
+
id
|
|
77
|
+
name
|
|
78
|
+
title
|
|
79
|
+
scope
|
|
80
|
+
userCount
|
|
81
|
+
systemRole
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
`;
|
|
86
|
+
return this.client.query(query, { first, search });
|
|
87
|
+
}
|
|
88
|
+
// ── Company Users ──────────────────────────────────────────
|
|
89
|
+
async listCompanyUsers(first = 25, search, where) {
|
|
90
|
+
const query = `
|
|
91
|
+
query ListCompanyUsers($first: Int, $search: String, $where: QueryCompanyUsersWhereWhereConditions) {
|
|
92
|
+
companyUsers(first: $first, search: $search, where: $where) {
|
|
93
|
+
data {
|
|
94
|
+
id
|
|
95
|
+
uuid
|
|
96
|
+
firstname
|
|
97
|
+
lastname
|
|
98
|
+
email
|
|
99
|
+
displayname
|
|
100
|
+
roles
|
|
101
|
+
}
|
|
102
|
+
paginatorInfo {
|
|
103
|
+
currentPage
|
|
104
|
+
lastPage
|
|
105
|
+
total
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
`;
|
|
110
|
+
return this.client.query(query, { first, search, where });
|
|
111
|
+
}
|
|
112
|
+
// ── User-Company Management ────────────────────────────────
|
|
113
|
+
async addUserToCompany(companyId, userId, roleId) {
|
|
114
|
+
const mutation = `
|
|
115
|
+
mutation AddUserToCompany($id: ID!, $user_id: ID!, $rol_id: ID) {
|
|
116
|
+
addUserToCompany(id: $id, user_id: $user_id, rol_id: $rol_id)
|
|
117
|
+
}
|
|
118
|
+
`;
|
|
119
|
+
return this.client.query(mutation, {
|
|
120
|
+
id: companyId,
|
|
121
|
+
user_id: userId,
|
|
122
|
+
rol_id: roleId,
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
async removeUserFromCompany(companyId, userId) {
|
|
126
|
+
const mutation = `
|
|
127
|
+
mutation RemoveUserFromCompany($id: ID!, $user_id: ID!) {
|
|
128
|
+
removeUserFromCompany(id: $id, user_id: $user_id)
|
|
129
|
+
}
|
|
130
|
+
`;
|
|
131
|
+
return this.client.query(mutation, { id: companyId, user_id: userId });
|
|
132
|
+
}
|
|
133
|
+
// ── User-Branch Management ─────────────────────────────────
|
|
134
|
+
async addUserToBranch(branchId, userId) {
|
|
135
|
+
const mutation = `
|
|
136
|
+
mutation AddUserToBranch($id: ID!, $user_id: ID!) {
|
|
137
|
+
addUserToBranch(id: $id, user_id: $user_id)
|
|
138
|
+
}
|
|
139
|
+
`;
|
|
140
|
+
return this.client.query(mutation, { id: branchId, user_id: userId });
|
|
141
|
+
}
|
|
142
|
+
async removeUserFromBranch(branchId, userId) {
|
|
143
|
+
const mutation = `
|
|
144
|
+
mutation RemoveUserFromBranch($id: ID!, $user_id: ID!) {
|
|
145
|
+
removeUserFromBranch(id: $id, user_id: $user_id)
|
|
146
|
+
}
|
|
147
|
+
`;
|
|
148
|
+
return this.client.query(mutation, { id: branchId, user_id: userId });
|
|
149
|
+
}
|
|
150
|
+
// ── Role Assignment ────────────────────────────────────────
|
|
151
|
+
async assignRoleToUser(userId, roleIds) {
|
|
152
|
+
const mutation = `
|
|
153
|
+
mutation AssignRoleToUser($userId: ID!, $roleIds: [ID!]!) {
|
|
154
|
+
assignRoleToUser(userId: $userId, roleIds: $roleIds)
|
|
155
|
+
}
|
|
156
|
+
`;
|
|
157
|
+
return this.client.query(mutation, { userId, roleIds });
|
|
158
|
+
}
|
|
159
|
+
async removeRoleFromUser(userId, role) {
|
|
160
|
+
const mutation = `
|
|
161
|
+
mutation RemoveRole($userId: ID!, $role: Mixed!) {
|
|
162
|
+
removeRole(userId: $userId, role: $role)
|
|
163
|
+
}
|
|
164
|
+
`;
|
|
165
|
+
return this.client.query(mutation, { userId, role });
|
|
166
|
+
}
|
|
167
|
+
}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
export class EventsService {
|
|
2
|
+
client;
|
|
3
|
+
constructor(client) {
|
|
4
|
+
this.client = client;
|
|
5
|
+
}
|
|
6
|
+
async listEvents(first = 25, search, where) {
|
|
7
|
+
const query = `
|
|
8
|
+
query ListEvents($first: Int, $search: String, $where: QueryEventsWhereWhereConditions) {
|
|
9
|
+
events(first: $first, search: $search, where: $where) {
|
|
10
|
+
data {
|
|
11
|
+
id
|
|
12
|
+
uuid
|
|
13
|
+
name
|
|
14
|
+
slug
|
|
15
|
+
description
|
|
16
|
+
created_at
|
|
17
|
+
updated_at
|
|
18
|
+
type { id name }
|
|
19
|
+
eventStatus { id name }
|
|
20
|
+
category { id name }
|
|
21
|
+
versions {
|
|
22
|
+
data {
|
|
23
|
+
id
|
|
24
|
+
start_at
|
|
25
|
+
end_at
|
|
26
|
+
dates {
|
|
27
|
+
id
|
|
28
|
+
date
|
|
29
|
+
start_time
|
|
30
|
+
end_time
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
paginatorInfo {
|
|
36
|
+
currentPage
|
|
37
|
+
lastPage
|
|
38
|
+
total
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
`;
|
|
43
|
+
return this.client.query(query, { first, search, where });
|
|
44
|
+
}
|
|
45
|
+
async getEvent(id) {
|
|
46
|
+
const query = `
|
|
47
|
+
query GetEvent($where: QueryEventsWhereWhereConditions) {
|
|
48
|
+
events(first: 1, where: $where) {
|
|
49
|
+
data {
|
|
50
|
+
id
|
|
51
|
+
uuid
|
|
52
|
+
name
|
|
53
|
+
slug
|
|
54
|
+
description
|
|
55
|
+
created_at
|
|
56
|
+
updated_at
|
|
57
|
+
type { id name }
|
|
58
|
+
eventStatus { id name }
|
|
59
|
+
category { id name }
|
|
60
|
+
resources_id
|
|
61
|
+
resources_type
|
|
62
|
+
versions {
|
|
63
|
+
data {
|
|
64
|
+
id
|
|
65
|
+
version
|
|
66
|
+
start_at
|
|
67
|
+
end_at
|
|
68
|
+
max_capacity
|
|
69
|
+
dates {
|
|
70
|
+
id
|
|
71
|
+
date
|
|
72
|
+
start_time
|
|
73
|
+
end_time
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
tags { id name }
|
|
78
|
+
custom_fields { name value }
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
`;
|
|
83
|
+
return this.client.query(query, {
|
|
84
|
+
where: { column: "ID", operator: "EQ", value: id },
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
async createEvent(input) {
|
|
88
|
+
const mutation = `
|
|
89
|
+
mutation CreateEvent($input: EventInput!) {
|
|
90
|
+
createEvent(input: $input) {
|
|
91
|
+
id
|
|
92
|
+
uuid
|
|
93
|
+
name
|
|
94
|
+
slug
|
|
95
|
+
description
|
|
96
|
+
created_at
|
|
97
|
+
type { id name }
|
|
98
|
+
eventStatus { id name }
|
|
99
|
+
versions {
|
|
100
|
+
data {
|
|
101
|
+
id
|
|
102
|
+
start_at
|
|
103
|
+
end_at
|
|
104
|
+
dates {
|
|
105
|
+
id
|
|
106
|
+
date
|
|
107
|
+
start_time
|
|
108
|
+
end_time
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
`;
|
|
115
|
+
return this.client.query(mutation, { input });
|
|
116
|
+
}
|
|
117
|
+
async updateEvent(id, input) {
|
|
118
|
+
const mutation = `
|
|
119
|
+
mutation UpdateEvent($id: ID!, $input: EventUpdateInput!) {
|
|
120
|
+
updateEvent(id: $id, input: $input) {
|
|
121
|
+
id
|
|
122
|
+
uuid
|
|
123
|
+
name
|
|
124
|
+
description
|
|
125
|
+
updated_at
|
|
126
|
+
type { id name }
|
|
127
|
+
eventStatus { id name }
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
`;
|
|
131
|
+
return this.client.query(mutation, { id, input });
|
|
132
|
+
}
|
|
133
|
+
async deleteEvent(id) {
|
|
134
|
+
const mutation = `
|
|
135
|
+
mutation DeleteEvent($id: ID!) {
|
|
136
|
+
deleteEvent(id: $id)
|
|
137
|
+
}
|
|
138
|
+
`;
|
|
139
|
+
return this.client.query(mutation, { id });
|
|
140
|
+
}
|
|
141
|
+
async followEvent(input) {
|
|
142
|
+
const mutation = `
|
|
143
|
+
mutation FollowEvent($input: FollowInput!) {
|
|
144
|
+
followEvent(input: $input)
|
|
145
|
+
}
|
|
146
|
+
`;
|
|
147
|
+
return this.client.query(mutation, { input });
|
|
148
|
+
}
|
|
149
|
+
async unFollowEvent(input) {
|
|
150
|
+
const mutation = `
|
|
151
|
+
mutation UnFollowEvent($input: FollowInput!) {
|
|
152
|
+
unFollowEvent(input: $input)
|
|
153
|
+
}
|
|
154
|
+
`;
|
|
155
|
+
return this.client.query(mutation, { input });
|
|
156
|
+
}
|
|
157
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -3,6 +3,7 @@ export class OrdersService {
|
|
|
3
3
|
constructor(client) {
|
|
4
4
|
this.client = client;
|
|
5
5
|
}
|
|
6
|
+
// ── Read ───────────────────────────────────────────────────
|
|
6
7
|
async searchOrders(search, first = 10) {
|
|
7
8
|
const query = `
|
|
8
9
|
query SearchOrders($first: Int!, $search: String) {
|
|
@@ -54,4 +55,148 @@ export class OrdersService {
|
|
|
54
55
|
where: { column: "ID", operator: "EQ", value: id },
|
|
55
56
|
});
|
|
56
57
|
}
|
|
58
|
+
// ── Lookups ────────────────────────────────────────────────
|
|
59
|
+
async listOrderStatuses(first = 50) {
|
|
60
|
+
const query = `
|
|
61
|
+
query ListOrderStatuses($first: Int) {
|
|
62
|
+
orderStatuses(first: $first) {
|
|
63
|
+
data {
|
|
64
|
+
id
|
|
65
|
+
name
|
|
66
|
+
slug
|
|
67
|
+
is_default
|
|
68
|
+
is_final
|
|
69
|
+
sequence
|
|
70
|
+
order_type_id
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
`;
|
|
75
|
+
return this.client.query(query, { first });
|
|
76
|
+
}
|
|
77
|
+
async listOrderTypes(first = 50) {
|
|
78
|
+
const query = `
|
|
79
|
+
query ListOrderTypes($first: Int) {
|
|
80
|
+
orderTypes(first: $first) {
|
|
81
|
+
data {
|
|
82
|
+
id
|
|
83
|
+
name
|
|
84
|
+
slug
|
|
85
|
+
title
|
|
86
|
+
total_statuses
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
`;
|
|
91
|
+
return this.client.query(query, { first });
|
|
92
|
+
}
|
|
93
|
+
async listRegions(first = 50) {
|
|
94
|
+
const query = `
|
|
95
|
+
query ListRegions($first: Int) {
|
|
96
|
+
regions(first: $first) {
|
|
97
|
+
data {
|
|
98
|
+
id
|
|
99
|
+
uuid
|
|
100
|
+
name
|
|
101
|
+
slug
|
|
102
|
+
currency
|
|
103
|
+
is_default
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
`;
|
|
108
|
+
return this.client.query(query, { first });
|
|
109
|
+
}
|
|
110
|
+
// ── Write ──────────────────────────────────────────────────
|
|
111
|
+
async createDraftOrder(input) {
|
|
112
|
+
const mutation = `
|
|
113
|
+
mutation CreateDraftOrder($input: DraftOrderInput!) {
|
|
114
|
+
createDraftOrder(input: $input) {
|
|
115
|
+
id
|
|
116
|
+
uuid
|
|
117
|
+
order_number
|
|
118
|
+
status
|
|
119
|
+
total_gross_amount
|
|
120
|
+
total_net_amount
|
|
121
|
+
created_at
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
`;
|
|
125
|
+
return this.client.query(mutation, { input });
|
|
126
|
+
}
|
|
127
|
+
async updateOrder(id, input) {
|
|
128
|
+
const mutation = `
|
|
129
|
+
mutation UpdateOrder($id: ID!, $input: UpdateOrderInput!) {
|
|
130
|
+
updateOrder(id: $id, input: $input) {
|
|
131
|
+
order {
|
|
132
|
+
id
|
|
133
|
+
uuid
|
|
134
|
+
order_number
|
|
135
|
+
status
|
|
136
|
+
fulfillment_status
|
|
137
|
+
payment_status
|
|
138
|
+
total_gross_amount
|
|
139
|
+
}
|
|
140
|
+
message
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
`;
|
|
144
|
+
return this.client.query(mutation, { id, input });
|
|
145
|
+
}
|
|
146
|
+
async updateDraftOrderStatus(orderId, status) {
|
|
147
|
+
const mutation = `
|
|
148
|
+
mutation UpdateDraftOrderStatus($order_id: ID!, $status: OrderStatusEnum!) {
|
|
149
|
+
updateDraftOrderStatus(order_id: $order_id, status: $status) {
|
|
150
|
+
id
|
|
151
|
+
uuid
|
|
152
|
+
order_number
|
|
153
|
+
status
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
`;
|
|
157
|
+
return this.client.query(mutation, { order_id: orderId, status });
|
|
158
|
+
}
|
|
159
|
+
async transitionOrderStatus(orderId, statusSlug, date) {
|
|
160
|
+
const mutation = `
|
|
161
|
+
mutation TransitionOrderStatus($input: TransitionOrderStatusInput!) {
|
|
162
|
+
transitionOrderStatus(input: $input) {
|
|
163
|
+
status
|
|
164
|
+
message
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
`;
|
|
168
|
+
return this.client.query(mutation, {
|
|
169
|
+
input: { order_id: orderId, status_slug: statusSlug, date },
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
async changeOrderCustomer(orderId, customerId) {
|
|
173
|
+
const mutation = `
|
|
174
|
+
mutation OrderChangeCustomer($order_id: ID!, $customer_id: ID!) {
|
|
175
|
+
orderChangeCustomer(order_id: $order_id, customer_id: $customer_id)
|
|
176
|
+
}
|
|
177
|
+
`;
|
|
178
|
+
return this.client.queryWithAppKey(mutation, {
|
|
179
|
+
order_id: orderId,
|
|
180
|
+
customer_id: customerId,
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
async deleteOrder(id) {
|
|
184
|
+
const mutation = `
|
|
185
|
+
mutation DeleteOrder($id: ID!) {
|
|
186
|
+
deleteOrder(id: $id)
|
|
187
|
+
}
|
|
188
|
+
`;
|
|
189
|
+
return this.client.query(mutation, { id });
|
|
190
|
+
}
|
|
191
|
+
async sendOrderEmail(orderId, template) {
|
|
192
|
+
const mutation = `
|
|
193
|
+
mutation SendOrderEmail($order_id: ID!, $template: String) {
|
|
194
|
+
sendOrderEmail(order_id: $order_id, template: $template)
|
|
195
|
+
}
|
|
196
|
+
`;
|
|
197
|
+
return this.client.queryWithAppKey(mutation, {
|
|
198
|
+
order_id: orderId,
|
|
199
|
+
template,
|
|
200
|
+
});
|
|
201
|
+
}
|
|
57
202
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/index.js
CHANGED
|
@@ -4,10 +4,16 @@ import { CrmService } from "./domains/crm/index.js";
|
|
|
4
4
|
import { InventoryService } from "./domains/inventory/index.js";
|
|
5
5
|
import { OrdersService } from "./domains/orders/index.js";
|
|
6
6
|
import { SocialService } from "./domains/social/index.js";
|
|
7
|
+
import { EcosystemService } from "./domains/ecosystem/index.js";
|
|
8
|
+
import { DealsService } from "./domains/deals/index.js";
|
|
9
|
+
import { EventsService } from "./domains/events/index.js";
|
|
7
10
|
import { registerCrmTools } from "./tools/crm.js";
|
|
8
11
|
import { registerInventoryTools } from "./tools/inventory.js";
|
|
9
12
|
import { registerOrdersTools } from "./tools/orders.js";
|
|
10
13
|
import { registerSocialTools } from "./tools/social.js";
|
|
14
|
+
import { registerEcosystemTools } from "./tools/ecosystem.js";
|
|
15
|
+
import { registerDealsTools } from "./tools/deals.js";
|
|
16
|
+
import { registerEventsTools } from "./tools/events.js";
|
|
11
17
|
import { toolResult } from "./tools/helpers.js";
|
|
12
18
|
const DEFAULT_API_URL = "https://graphapi.kanvas.dev/graphql";
|
|
13
19
|
// OpenClaw v2026.4.5+ calls register() per-agent-context (main, subagents,
|
|
@@ -20,6 +26,9 @@ let sharedCrm = null;
|
|
|
20
26
|
let sharedInventory = null;
|
|
21
27
|
let sharedOrders = null;
|
|
22
28
|
let sharedSocial = null;
|
|
29
|
+
let sharedEcosystem = null;
|
|
30
|
+
let sharedDeals = null;
|
|
31
|
+
let sharedEvents = null;
|
|
23
32
|
let startupBannerShown = false;
|
|
24
33
|
let skipBannerShown = false;
|
|
25
34
|
function resolveConfig(pluginConfig) {
|
|
@@ -111,6 +120,9 @@ export default {
|
|
|
111
120
|
sharedInventory = new InventoryService(sharedClient);
|
|
112
121
|
sharedOrders = new OrdersService(sharedClient);
|
|
113
122
|
sharedSocial = new SocialService(sharedClient);
|
|
123
|
+
sharedEcosystem = new EcosystemService(sharedClient);
|
|
124
|
+
sharedDeals = new DealsService(sharedClient);
|
|
125
|
+
sharedEvents = new EventsService(sharedClient);
|
|
114
126
|
}
|
|
115
127
|
// Tools and hooks must be registered on every api object — each one is
|
|
116
128
|
// a separate agent context (main, subagents, cron lanes).
|
|
@@ -119,6 +131,9 @@ export default {
|
|
|
119
131
|
registerInventoryTools(api, sharedInventory, ensureAuth);
|
|
120
132
|
registerOrdersTools(api, sharedOrders, ensureAuth);
|
|
121
133
|
registerSocialTools(api, sharedSocial, ensureAuth);
|
|
134
|
+
registerEcosystemTools(api, sharedEcosystem, ensureAuth);
|
|
135
|
+
registerDealsTools(api, sharedDeals, ensureAuth);
|
|
136
|
+
registerEventsTools(api, sharedEvents, ensureAuth);
|
|
122
137
|
api.registerTool({
|
|
123
138
|
name: "kanvas_test_connection",
|
|
124
139
|
label: "Test Connection",
|
|
@@ -143,7 +158,7 @@ export default {
|
|
|
143
158
|
}, { commands: ["setup"] });
|
|
144
159
|
if (!startupBannerShown) {
|
|
145
160
|
startupBannerShown = true;
|
|
146
|
-
api.logger.info("Kanvas plugin registered —
|
|
161
|
+
api.logger.info("Kanvas plugin registered — 73 tools loaded");
|
|
147
162
|
}
|
|
148
163
|
},
|
|
149
164
|
};
|
|
@@ -217,6 +232,16 @@ Use when the user asks about products, stock, warehouses, or catalog.
|
|
|
217
232
|
Use when the user asks about orders, purchases, or sales.
|
|
218
233
|
- \`kanvas_search_orders\` → find orders by number or keyword
|
|
219
234
|
- \`kanvas_get_order\` → full order detail with items, customer, status
|
|
235
|
+
- \`kanvas_list_order_statuses\` → get status slugs for transitions
|
|
236
|
+
- \`kanvas_list_order_types\` → order type pipelines (standard, subscription, etc.)
|
|
237
|
+
- \`kanvas_list_regions\` → regions for order creation (get region_id)
|
|
238
|
+
- \`kanvas_create_draft_order\` → create a draft order. Requires email, customer, region_id (from kanvas_list_regions), and items with variant_id+quantity (from kanvas_list_variants)
|
|
239
|
+
- \`kanvas_update_order\` → update items, status, metadata
|
|
240
|
+
- \`kanvas_update_draft_order_status\` → change draft order status (PENDING, COMPLETED, DRAFT, CANCELED, FAILED)
|
|
241
|
+
- \`kanvas_transition_order_status\` → move through the order status pipeline (use status_slug from kanvas_list_order_statuses)
|
|
242
|
+
- \`kanvas_order_change_customer\` → change the customer on an order (requires xKanvasKey)
|
|
243
|
+
- \`kanvas_delete_order\` → delete an order
|
|
244
|
+
- \`kanvas_send_order_email\` → send a confirmation/receipt email (requires xKanvasKey)
|
|
220
245
|
|
|
221
246
|
**Follow-ups & Reminders**
|
|
222
247
|
ALWAYS schedule follow-ups in Kanvas so the human team can see them — NEVER store them only in local memory.
|
|
@@ -224,6 +249,36 @@ ALWAYS schedule follow-ups in Kanvas so the human team can see them — NEVER st
|
|
|
224
249
|
- \`kanvas_list_events\` → list scheduled events/follow-ups
|
|
225
250
|
- For structured follow-up data (tracking status, priority, custom fields), use \`kanvas_create_message\` with verb "follow_up" and a JSON payload containing { due_date, lead_id, action, status, priority }.
|
|
226
251
|
|
|
252
|
+
**Deals (Sales Opportunities)**
|
|
253
|
+
Use when the user asks about deals, opportunities, sales tracking. A deal is a potential sale, often tied to a lead/person/organization and moved through a pipeline.
|
|
254
|
+
- \`kanvas_list_deals\` → list/search deals with owner, pipeline, stage, status
|
|
255
|
+
- \`kanvas_get_deal\` → full deal detail including tags and custom fields
|
|
256
|
+
- \`kanvas_create_deal\` → create a deal (only title required; optionally link to lead, person, org, pipeline, owner)
|
|
257
|
+
- \`kanvas_update_deal\` → update title, description, pipeline stage, owner, linked entities
|
|
258
|
+
- \`kanvas_delete_deal\` → delete a deal
|
|
259
|
+
|
|
260
|
+
**Events (Full event management)**
|
|
261
|
+
For simple follow-ups linked to a lead, prefer \`kanvas_create_follow_up\`. Use these when the user wants richer event management (categories, types, resources, tags).
|
|
262
|
+
- \`kanvas_list_events_full\` → list events with versions and dates
|
|
263
|
+
- \`kanvas_get_event\` → event detail including versions, tags, custom fields
|
|
264
|
+
- \`kanvas_create_event\` → create an event with one or more dates. Supports linking to resources (leads, deals), categories, types, tags.
|
|
265
|
+
- \`kanvas_update_event\` → update name, description, dates, status
|
|
266
|
+
- \`kanvas_delete_event\` → delete an event
|
|
267
|
+
- \`kanvas_follow_event\` / \`kanvas_unfollow_event\` → subscribe/unsubscribe user to event updates
|
|
268
|
+
|
|
269
|
+
**Ecosystem (Companies, Branches, Roles, Users)**
|
|
270
|
+
Use when the user asks about companies, branches/locations, user management, roles, or permissions.
|
|
271
|
+
- \`kanvas_list_companies\` → list/search companies
|
|
272
|
+
- \`kanvas_list_branches\` → list/search branches (filter by companies_id for a specific company)
|
|
273
|
+
- \`kanvas_list_roles\` → list available roles (find role IDs like "super admin")
|
|
274
|
+
- \`kanvas_list_company_users\` → list users in the current company
|
|
275
|
+
- \`kanvas_add_user_to_company\` → add a user to a company with optional role
|
|
276
|
+
- \`kanvas_remove_user_from_company\` → remove a user from a company
|
|
277
|
+
- \`kanvas_add_user_to_branch\` → add a user to a branch/location
|
|
278
|
+
- \`kanvas_remove_user_from_branch\` → remove a user from a branch
|
|
279
|
+
- \`kanvas_assign_role_to_user\` → assign roles (e.g. super admin). Call \`kanvas_list_roles\` first to get role IDs.
|
|
280
|
+
- \`kanvas_remove_role_from_user\` → remove a role from a user
|
|
281
|
+
|
|
227
282
|
**Diagnostics**
|
|
228
283
|
- \`kanvas_test_connection\` → verify the API is reachable
|
|
229
284
|
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { Type } from "@sinclair/typebox";
|
|
2
|
+
import { toolResult } from "./helpers.js";
|
|
3
|
+
const WhereClause = Type.Optional(Type.Array(Type.Object({
|
|
4
|
+
column: Type.String(),
|
|
5
|
+
operator: Type.String({ description: 'e.g. "EQ", "LIKE"' }),
|
|
6
|
+
value: Type.Unknown(),
|
|
7
|
+
}), { description: "Filter conditions" }));
|
|
8
|
+
export function registerDealsTools(api, service, ensureAuth) {
|
|
9
|
+
api.registerTool({
|
|
10
|
+
name: "kanvas_list_deals",
|
|
11
|
+
label: "List Deals",
|
|
12
|
+
description: "List or search deals. A deal represents a potential sale/opportunity linked to a lead, person, or organization.",
|
|
13
|
+
parameters: Type.Object({
|
|
14
|
+
first: Type.Optional(Type.Number({ description: "Max results (default 25)" })),
|
|
15
|
+
search: Type.Optional(Type.String({ description: "Search keyword" })),
|
|
16
|
+
where: WhereClause,
|
|
17
|
+
}),
|
|
18
|
+
async execute(_id, params) {
|
|
19
|
+
await ensureAuth();
|
|
20
|
+
return toolResult(await service.listDeals(params.first, params.search, params.where));
|
|
21
|
+
},
|
|
22
|
+
});
|
|
23
|
+
api.registerTool({
|
|
24
|
+
name: "kanvas_get_deal",
|
|
25
|
+
label: "Get Deal",
|
|
26
|
+
description: "Get full details for a deal by ID, including pipeline stage, owner, linked lead/person/org, tags, and custom fields.",
|
|
27
|
+
parameters: Type.Object({
|
|
28
|
+
id: Type.String({ description: "Deal ID" }),
|
|
29
|
+
}),
|
|
30
|
+
async execute(_id, params) {
|
|
31
|
+
await ensureAuth();
|
|
32
|
+
return toolResult(await service.getDeal(params.id));
|
|
33
|
+
},
|
|
34
|
+
});
|
|
35
|
+
api.registerTool({
|
|
36
|
+
name: "kanvas_create_deal",
|
|
37
|
+
label: "Create Deal",
|
|
38
|
+
description: "Create a deal. Only title is required. Optionally link to a lead, person, organization, or pipeline stage.",
|
|
39
|
+
parameters: Type.Object({
|
|
40
|
+
title: Type.String({ description: "Deal title" }),
|
|
41
|
+
description: Type.Optional(Type.String()),
|
|
42
|
+
leads_id: Type.Optional(Type.Union([Type.String(), Type.Number()], { description: "Linked lead ID" })),
|
|
43
|
+
people_id: Type.Optional(Type.Union([Type.String(), Type.Number()], { description: "Linked person ID" })),
|
|
44
|
+
organization_id: Type.Optional(Type.Union([Type.String(), Type.Number()])),
|
|
45
|
+
owner_id: Type.Optional(Type.Union([Type.String(), Type.Number()], { description: "Deal owner user ID" })),
|
|
46
|
+
pipeline_id: Type.Optional(Type.Union([Type.String(), Type.Number()])),
|
|
47
|
+
pipeline_stage_id: Type.Optional(Type.Union([Type.String(), Type.Number()])),
|
|
48
|
+
status_id: Type.Optional(Type.Number()),
|
|
49
|
+
companies_branches_id: Type.Optional(Type.Union([Type.String(), Type.Number()])),
|
|
50
|
+
}),
|
|
51
|
+
async execute(_id, params) {
|
|
52
|
+
await ensureAuth();
|
|
53
|
+
return toolResult(await service.createDeal(params));
|
|
54
|
+
},
|
|
55
|
+
});
|
|
56
|
+
api.registerTool({
|
|
57
|
+
name: "kanvas_update_deal",
|
|
58
|
+
label: "Update Deal",
|
|
59
|
+
description: "Update a deal's title, description, pipeline stage, owner, or linked entities.",
|
|
60
|
+
parameters: Type.Object({
|
|
61
|
+
id: Type.String({ description: "Deal ID" }),
|
|
62
|
+
title: Type.Optional(Type.String()),
|
|
63
|
+
description: Type.Optional(Type.String()),
|
|
64
|
+
leads_id: Type.Optional(Type.Union([Type.String(), Type.Number()])),
|
|
65
|
+
people_id: Type.Optional(Type.Union([Type.String(), Type.Number()])),
|
|
66
|
+
organization_id: Type.Optional(Type.Union([Type.String(), Type.Number()])),
|
|
67
|
+
owner_id: Type.Optional(Type.Union([Type.String(), Type.Number()])),
|
|
68
|
+
pipeline_id: Type.Optional(Type.Union([Type.String(), Type.Number()])),
|
|
69
|
+
pipeline_stage_id: Type.Optional(Type.Union([Type.String(), Type.Number()])),
|
|
70
|
+
status_id: Type.Optional(Type.Number()),
|
|
71
|
+
companies_branches_id: Type.Optional(Type.Union([Type.String(), Type.Number()])),
|
|
72
|
+
}),
|
|
73
|
+
async execute(_id, params) {
|
|
74
|
+
await ensureAuth();
|
|
75
|
+
const { id, ...input } = params;
|
|
76
|
+
return toolResult(await service.updateDeal(id, input));
|
|
77
|
+
},
|
|
78
|
+
});
|
|
79
|
+
api.registerTool({
|
|
80
|
+
name: "kanvas_delete_deal",
|
|
81
|
+
label: "Delete Deal",
|
|
82
|
+
description: "Delete a deal by ID.",
|
|
83
|
+
parameters: Type.Object({
|
|
84
|
+
id: Type.String({ description: "Deal ID" }),
|
|
85
|
+
}),
|
|
86
|
+
async execute(_id, params) {
|
|
87
|
+
await ensureAuth();
|
|
88
|
+
return toolResult(await service.deleteDeal(params.id));
|
|
89
|
+
},
|
|
90
|
+
});
|
|
91
|
+
}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { Type } from "@sinclair/typebox";
|
|
2
|
+
import { toolResult } from "./helpers.js";
|
|
3
|
+
const WhereClause = Type.Optional(Type.Array(Type.Object({
|
|
4
|
+
column: Type.String(),
|
|
5
|
+
operator: Type.String({ description: 'e.g. "EQ", "LIKE"' }),
|
|
6
|
+
value: Type.Unknown(),
|
|
7
|
+
}), { description: "Filter conditions" }));
|
|
8
|
+
export function registerEcosystemTools(api, service, ensureAuth) {
|
|
9
|
+
// ── Read tools ─────────────────────────────────────────────
|
|
10
|
+
api.registerTool({
|
|
11
|
+
name: "kanvas_list_companies",
|
|
12
|
+
label: "List Companies",
|
|
13
|
+
description: "List or search companies in the Kanvas ecosystem.",
|
|
14
|
+
parameters: Type.Object({
|
|
15
|
+
first: Type.Optional(Type.Number({ description: "Max results (default 25)" })),
|
|
16
|
+
search: Type.Optional(Type.String({ description: "Search keyword" })),
|
|
17
|
+
where: WhereClause,
|
|
18
|
+
}),
|
|
19
|
+
async execute(_id, params) {
|
|
20
|
+
await ensureAuth();
|
|
21
|
+
return toolResult(await service.listCompanies(params.first, params.search, params.where));
|
|
22
|
+
},
|
|
23
|
+
});
|
|
24
|
+
api.registerTool({
|
|
25
|
+
name: "kanvas_list_branches",
|
|
26
|
+
label: "List Branches",
|
|
27
|
+
description: "List or search company branches. Filter by companies_id to get branches for a specific company.",
|
|
28
|
+
parameters: Type.Object({
|
|
29
|
+
first: Type.Optional(Type.Number({ description: "Max results (default 25)" })),
|
|
30
|
+
search: Type.Optional(Type.String({ description: "Search keyword" })),
|
|
31
|
+
where: WhereClause,
|
|
32
|
+
}),
|
|
33
|
+
async execute(_id, params) {
|
|
34
|
+
await ensureAuth();
|
|
35
|
+
return toolResult(await service.listBranches(params.first, params.search, params.where));
|
|
36
|
+
},
|
|
37
|
+
});
|
|
38
|
+
api.registerTool({
|
|
39
|
+
name: "kanvas_list_roles",
|
|
40
|
+
label: "List Roles",
|
|
41
|
+
description: "List available roles. Use this to find role IDs (e.g. super admin) before assigning roles to users.",
|
|
42
|
+
parameters: Type.Object({
|
|
43
|
+
first: Type.Optional(Type.Number({ description: "Max results (default 50)" })),
|
|
44
|
+
search: Type.Optional(Type.String({ description: "Search by role name" })),
|
|
45
|
+
}),
|
|
46
|
+
async execute(_id, params) {
|
|
47
|
+
await ensureAuth();
|
|
48
|
+
return toolResult(await service.listRoles(params.first, params.search));
|
|
49
|
+
},
|
|
50
|
+
});
|
|
51
|
+
api.registerTool({
|
|
52
|
+
name: "kanvas_list_company_users",
|
|
53
|
+
label: "List Company Users",
|
|
54
|
+
description: "List users in the current company. Supports search and filtering by user fields.",
|
|
55
|
+
parameters: Type.Object({
|
|
56
|
+
first: Type.Optional(Type.Number({ description: "Max results (default 25)" })),
|
|
57
|
+
search: Type.Optional(Type.String({ description: "Search keyword" })),
|
|
58
|
+
where: WhereClause,
|
|
59
|
+
}),
|
|
60
|
+
async execute(_id, params) {
|
|
61
|
+
await ensureAuth();
|
|
62
|
+
return toolResult(await service.listCompanyUsers(params.first, params.search, params.where));
|
|
63
|
+
},
|
|
64
|
+
});
|
|
65
|
+
// ── Write tools ────────────────────────────────────────────
|
|
66
|
+
api.registerTool({
|
|
67
|
+
name: "kanvas_add_user_to_company",
|
|
68
|
+
label: "Add User to Company",
|
|
69
|
+
description: "Add an existing user to a company, optionally with a specific role.",
|
|
70
|
+
parameters: Type.Object({
|
|
71
|
+
company_id: Type.String({ description: "Company ID" }),
|
|
72
|
+
user_id: Type.String({ description: "User ID" }),
|
|
73
|
+
role_id: Type.Optional(Type.String({ description: "Role ID (use kanvas_list_roles to find it)" })),
|
|
74
|
+
}),
|
|
75
|
+
async execute(_id, params) {
|
|
76
|
+
await ensureAuth();
|
|
77
|
+
return toolResult(await service.addUserToCompany(params.company_id, params.user_id, params.role_id));
|
|
78
|
+
},
|
|
79
|
+
});
|
|
80
|
+
api.registerTool({
|
|
81
|
+
name: "kanvas_remove_user_from_company",
|
|
82
|
+
label: "Remove User from Company",
|
|
83
|
+
description: "Remove a user from a company.",
|
|
84
|
+
parameters: Type.Object({
|
|
85
|
+
company_id: Type.String({ description: "Company ID" }),
|
|
86
|
+
user_id: Type.String({ description: "User ID" }),
|
|
87
|
+
}),
|
|
88
|
+
async execute(_id, params) {
|
|
89
|
+
await ensureAuth();
|
|
90
|
+
return toolResult(await service.removeUserFromCompany(params.company_id, params.user_id));
|
|
91
|
+
},
|
|
92
|
+
});
|
|
93
|
+
api.registerTool({
|
|
94
|
+
name: "kanvas_add_user_to_branch",
|
|
95
|
+
label: "Add User to Branch",
|
|
96
|
+
description: "Add a user to a company branch/location.",
|
|
97
|
+
parameters: Type.Object({
|
|
98
|
+
branch_id: Type.String({ description: "Branch ID" }),
|
|
99
|
+
user_id: Type.String({ description: "User ID" }),
|
|
100
|
+
}),
|
|
101
|
+
async execute(_id, params) {
|
|
102
|
+
await ensureAuth();
|
|
103
|
+
return toolResult(await service.addUserToBranch(params.branch_id, params.user_id));
|
|
104
|
+
},
|
|
105
|
+
});
|
|
106
|
+
api.registerTool({
|
|
107
|
+
name: "kanvas_remove_user_from_branch",
|
|
108
|
+
label: "Remove User from Branch",
|
|
109
|
+
description: "Remove a user from a company branch/location.",
|
|
110
|
+
parameters: Type.Object({
|
|
111
|
+
branch_id: Type.String({ description: "Branch ID" }),
|
|
112
|
+
user_id: Type.String({ description: "User ID" }),
|
|
113
|
+
}),
|
|
114
|
+
async execute(_id, params) {
|
|
115
|
+
await ensureAuth();
|
|
116
|
+
return toolResult(await service.removeUserFromBranch(params.branch_id, params.user_id));
|
|
117
|
+
},
|
|
118
|
+
});
|
|
119
|
+
api.registerTool({
|
|
120
|
+
name: "kanvas_assign_role_to_user",
|
|
121
|
+
label: "Assign Role to User",
|
|
122
|
+
description: "Assign one or more roles to a user. Requires admin privileges. Use kanvas_list_roles to find role IDs.",
|
|
123
|
+
parameters: Type.Object({
|
|
124
|
+
user_id: Type.String({ description: "User ID" }),
|
|
125
|
+
role_ids: Type.Array(Type.String(), { description: "Array of role IDs to assign" }),
|
|
126
|
+
}),
|
|
127
|
+
async execute(_id, params) {
|
|
128
|
+
await ensureAuth();
|
|
129
|
+
return toolResult(await service.assignRoleToUser(params.user_id, params.role_ids));
|
|
130
|
+
},
|
|
131
|
+
});
|
|
132
|
+
api.registerTool({
|
|
133
|
+
name: "kanvas_remove_role_from_user",
|
|
134
|
+
label: "Remove Role from User",
|
|
135
|
+
description: "Remove a role from a user. The role parameter can be the role ID or name.",
|
|
136
|
+
parameters: Type.Object({
|
|
137
|
+
user_id: Type.String({ description: "User ID" }),
|
|
138
|
+
role: Type.String({ description: "Role ID or name to remove" }),
|
|
139
|
+
}),
|
|
140
|
+
async execute(_id, params) {
|
|
141
|
+
await ensureAuth();
|
|
142
|
+
return toolResult(await service.removeRoleFromUser(params.user_id, params.role));
|
|
143
|
+
},
|
|
144
|
+
});
|
|
145
|
+
}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { Type } from "@sinclair/typebox";
|
|
2
|
+
import { toolResult } from "./helpers.js";
|
|
3
|
+
const WhereClause = Type.Optional(Type.Array(Type.Object({
|
|
4
|
+
column: Type.String(),
|
|
5
|
+
operator: Type.String({ description: 'e.g. "EQ", "LIKE"' }),
|
|
6
|
+
value: Type.Unknown(),
|
|
7
|
+
}), { description: "Filter conditions" }));
|
|
8
|
+
const EventDateInput = Type.Object({
|
|
9
|
+
date: Type.String({ description: "YYYY-MM-DD" }),
|
|
10
|
+
start_time: Type.String({ description: "HH:MM (24h)" }),
|
|
11
|
+
end_time: Type.String({ description: "HH:MM (24h)" }),
|
|
12
|
+
});
|
|
13
|
+
const EventResourceInput = Type.Object({
|
|
14
|
+
resources_id: Type.String({ description: "Entity ID this event is attached to" }),
|
|
15
|
+
resources_type: Type.String({ description: 'e.g. "lead", "deal"' }),
|
|
16
|
+
});
|
|
17
|
+
const TagInput = Type.Object({
|
|
18
|
+
name: Type.String(),
|
|
19
|
+
slug: Type.Optional(Type.String()),
|
|
20
|
+
});
|
|
21
|
+
export function registerEventsTools(api, service, ensureAuth) {
|
|
22
|
+
api.registerTool({
|
|
23
|
+
name: "kanvas_list_events_full",
|
|
24
|
+
label: "List Events (full)",
|
|
25
|
+
description: "List or search events with full details. For follow-ups only, see kanvas_list_events.",
|
|
26
|
+
parameters: Type.Object({
|
|
27
|
+
first: Type.Optional(Type.Number({ description: "Max results (default 25)" })),
|
|
28
|
+
search: Type.Optional(Type.String({ description: "Search keyword" })),
|
|
29
|
+
where: WhereClause,
|
|
30
|
+
}),
|
|
31
|
+
async execute(_id, params) {
|
|
32
|
+
await ensureAuth();
|
|
33
|
+
return toolResult(await service.listEvents(params.first, params.search, params.where));
|
|
34
|
+
},
|
|
35
|
+
});
|
|
36
|
+
api.registerTool({
|
|
37
|
+
name: "kanvas_get_event",
|
|
38
|
+
label: "Get Event",
|
|
39
|
+
description: "Get full details for an event by ID, including versions, dates, tags, and custom fields.",
|
|
40
|
+
parameters: Type.Object({
|
|
41
|
+
id: Type.String({ description: "Event ID" }),
|
|
42
|
+
}),
|
|
43
|
+
async execute(_id, params) {
|
|
44
|
+
await ensureAuth();
|
|
45
|
+
return toolResult(await service.getEvent(params.id));
|
|
46
|
+
},
|
|
47
|
+
});
|
|
48
|
+
api.registerTool({
|
|
49
|
+
name: "kanvas_create_event",
|
|
50
|
+
label: "Create Event",
|
|
51
|
+
description: "Create an event with dates. Supports linking to resources (leads, deals) and categorization. For a simple lead follow-up, use kanvas_create_follow_up.",
|
|
52
|
+
parameters: Type.Object({
|
|
53
|
+
name: Type.String({ description: "Event name" }),
|
|
54
|
+
slug: Type.Optional(Type.String()),
|
|
55
|
+
description: Type.Optional(Type.String()),
|
|
56
|
+
dates: Type.Array(EventDateInput, { description: "At least one date (YYYY-MM-DD + HH:MM times)" }),
|
|
57
|
+
type_id: Type.Optional(Type.Union([Type.String(), Type.Number()])),
|
|
58
|
+
status_id: Type.Optional(Type.Union([Type.String(), Type.Number()])),
|
|
59
|
+
class_id: Type.Optional(Type.Union([Type.String(), Type.Number()])),
|
|
60
|
+
category_id: Type.Optional(Type.Union([Type.String(), Type.Number()])),
|
|
61
|
+
theme_id: Type.Optional(Type.Union([Type.String(), Type.Number()])),
|
|
62
|
+
theme_area_id: Type.Optional(Type.Union([Type.String(), Type.Number()])),
|
|
63
|
+
resources: Type.Optional(Type.Array(EventResourceInput)),
|
|
64
|
+
participants: Type.Optional(Type.Array(Type.String())),
|
|
65
|
+
tags: Type.Optional(Type.Array(TagInput)),
|
|
66
|
+
custom_fields: Type.Optional(Type.Array(Type.Record(Type.String(), Type.Unknown()))),
|
|
67
|
+
}),
|
|
68
|
+
async execute(_id, params) {
|
|
69
|
+
await ensureAuth();
|
|
70
|
+
return toolResult(await service.createEvent(params));
|
|
71
|
+
},
|
|
72
|
+
});
|
|
73
|
+
api.registerTool({
|
|
74
|
+
name: "kanvas_update_event",
|
|
75
|
+
label: "Update Event",
|
|
76
|
+
description: "Update an event's name, description, dates, status, or linked resources.",
|
|
77
|
+
parameters: Type.Object({
|
|
78
|
+
id: Type.String({ description: "Event ID" }),
|
|
79
|
+
name: Type.Optional(Type.String()),
|
|
80
|
+
description: Type.Optional(Type.String()),
|
|
81
|
+
dates: Type.Optional(Type.Array(EventDateInput)),
|
|
82
|
+
type_id: Type.Optional(Type.Union([Type.String(), Type.Number()])),
|
|
83
|
+
status_id: Type.Optional(Type.Union([Type.String(), Type.Number()])),
|
|
84
|
+
class_id: Type.Optional(Type.Union([Type.String(), Type.Number()])),
|
|
85
|
+
category_id: Type.Optional(Type.Union([Type.String(), Type.Number()])),
|
|
86
|
+
resources_id: Type.Optional(Type.Union([Type.String(), Type.Number()])),
|
|
87
|
+
resources_type: Type.Optional(Type.String()),
|
|
88
|
+
tags: Type.Optional(Type.Array(TagInput)),
|
|
89
|
+
}),
|
|
90
|
+
async execute(_id, params) {
|
|
91
|
+
await ensureAuth();
|
|
92
|
+
const { id, ...input } = params;
|
|
93
|
+
return toolResult(await service.updateEvent(id, input));
|
|
94
|
+
},
|
|
95
|
+
});
|
|
96
|
+
api.registerTool({
|
|
97
|
+
name: "kanvas_delete_event",
|
|
98
|
+
label: "Delete Event",
|
|
99
|
+
description: "Delete an event by ID.",
|
|
100
|
+
parameters: Type.Object({
|
|
101
|
+
id: Type.String({ description: "Event ID" }),
|
|
102
|
+
}),
|
|
103
|
+
async execute(_id, params) {
|
|
104
|
+
await ensureAuth();
|
|
105
|
+
return toolResult(await service.deleteEvent(params.id));
|
|
106
|
+
},
|
|
107
|
+
});
|
|
108
|
+
api.registerTool({
|
|
109
|
+
name: "kanvas_follow_event",
|
|
110
|
+
label: "Follow Event",
|
|
111
|
+
description: "Subscribe a user to event updates.",
|
|
112
|
+
parameters: Type.Object({
|
|
113
|
+
entity_id: Type.String({ description: "Event UUID" }),
|
|
114
|
+
user_id: Type.Union([Type.String(), Type.Number()], { description: "User ID" }),
|
|
115
|
+
}),
|
|
116
|
+
async execute(_id, params) {
|
|
117
|
+
await ensureAuth();
|
|
118
|
+
return toolResult(await service.followEvent(params));
|
|
119
|
+
},
|
|
120
|
+
});
|
|
121
|
+
api.registerTool({
|
|
122
|
+
name: "kanvas_unfollow_event",
|
|
123
|
+
label: "Unfollow Event",
|
|
124
|
+
description: "Unsubscribe a user from event updates.",
|
|
125
|
+
parameters: Type.Object({
|
|
126
|
+
entity_id: Type.String({ description: "Event UUID" }),
|
|
127
|
+
user_id: Type.Union([Type.String(), Type.Number()], { description: "User ID" }),
|
|
128
|
+
}),
|
|
129
|
+
async execute(_id, params) {
|
|
130
|
+
await ensureAuth();
|
|
131
|
+
return toolResult(await service.unFollowEvent(params));
|
|
132
|
+
},
|
|
133
|
+
});
|
|
134
|
+
}
|
package/dist/tools/orders.js
CHANGED
|
@@ -1,6 +1,42 @@
|
|
|
1
1
|
import { Type } from "@sinclair/typebox";
|
|
2
2
|
import { toolResult } from "./helpers.js";
|
|
3
|
+
const OrderLineItemInput = Type.Object({
|
|
4
|
+
variant_id: Type.Union([Type.String(), Type.Number()], { description: "Variant ID" }),
|
|
5
|
+
quantity: Type.Number({ description: "Quantity" }),
|
|
6
|
+
price: Type.Optional(Type.Union([Type.String(), Type.Number()])),
|
|
7
|
+
metadata: Type.Optional(Type.Record(Type.String(), Type.Unknown())),
|
|
8
|
+
channel_id: Type.Optional(Type.Union([Type.String(), Type.Number()])),
|
|
9
|
+
});
|
|
10
|
+
const OrderAddressInput = Type.Object({
|
|
11
|
+
address: Type.String(),
|
|
12
|
+
address_2: Type.Optional(Type.String()),
|
|
13
|
+
city: Type.Optional(Type.String()),
|
|
14
|
+
state: Type.Optional(Type.String()),
|
|
15
|
+
zip: Type.Optional(Type.String()),
|
|
16
|
+
country: Type.Optional(Type.String()),
|
|
17
|
+
is_default: Type.Optional(Type.Boolean()),
|
|
18
|
+
});
|
|
19
|
+
const OrderBillingInput = Type.Object({
|
|
20
|
+
address: Type.String(),
|
|
21
|
+
address2: Type.Optional(Type.String()),
|
|
22
|
+
city: Type.String(),
|
|
23
|
+
state: Type.String(),
|
|
24
|
+
zip: Type.String(),
|
|
25
|
+
country: Type.String(),
|
|
26
|
+
});
|
|
27
|
+
const OrderCustomerInput = Type.Object({
|
|
28
|
+
id: Type.Optional(Type.Union([Type.String(), Type.Number()])),
|
|
29
|
+
firstname: Type.String(),
|
|
30
|
+
lastname: Type.Optional(Type.String()),
|
|
31
|
+
contacts: Type.Optional(Type.Array(Type.Object({
|
|
32
|
+
value: Type.String(),
|
|
33
|
+
contacts_types_id: Type.Number(),
|
|
34
|
+
weight: Type.Optional(Type.Number()),
|
|
35
|
+
}))),
|
|
36
|
+
address: Type.Optional(Type.Array(OrderAddressInput)),
|
|
37
|
+
});
|
|
3
38
|
export function registerOrdersTools(api, service, ensureAuth) {
|
|
39
|
+
// ── Read ───────────────────────────────────────────────────
|
|
4
40
|
api.registerTool({
|
|
5
41
|
name: "kanvas_search_orders",
|
|
6
42
|
label: "Search Orders",
|
|
@@ -26,4 +62,153 @@ export function registerOrdersTools(api, service, ensureAuth) {
|
|
|
26
62
|
return toolResult(await service.getOrder(params.id));
|
|
27
63
|
},
|
|
28
64
|
});
|
|
65
|
+
// ── Lookups ────────────────────────────────────────────────
|
|
66
|
+
api.registerTool({
|
|
67
|
+
name: "kanvas_list_order_statuses",
|
|
68
|
+
label: "List Order Statuses",
|
|
69
|
+
description: "List order statuses. Use to find status slugs for status transitions.",
|
|
70
|
+
parameters: Type.Object({
|
|
71
|
+
first: Type.Optional(Type.Number({ description: "Max results (default 50)" })),
|
|
72
|
+
}),
|
|
73
|
+
async execute(_id, params) {
|
|
74
|
+
await ensureAuth();
|
|
75
|
+
return toolResult(await service.listOrderStatuses(params.first));
|
|
76
|
+
},
|
|
77
|
+
});
|
|
78
|
+
api.registerTool({
|
|
79
|
+
name: "kanvas_list_order_types",
|
|
80
|
+
label: "List Order Types",
|
|
81
|
+
description: "List order types (e.g. standard, subscription). Each type has its own status pipeline.",
|
|
82
|
+
parameters: Type.Object({
|
|
83
|
+
first: Type.Optional(Type.Number({ description: "Max results (default 50)" })),
|
|
84
|
+
}),
|
|
85
|
+
async execute(_id, params) {
|
|
86
|
+
await ensureAuth();
|
|
87
|
+
return toolResult(await service.listOrderTypes(params.first));
|
|
88
|
+
},
|
|
89
|
+
});
|
|
90
|
+
api.registerTool({
|
|
91
|
+
name: "kanvas_list_regions",
|
|
92
|
+
label: "List Regions",
|
|
93
|
+
description: "List regions for order creation. Regions define currency and tax rules.",
|
|
94
|
+
parameters: Type.Object({
|
|
95
|
+
first: Type.Optional(Type.Number({ description: "Max results (default 50)" })),
|
|
96
|
+
}),
|
|
97
|
+
async execute(_id, params) {
|
|
98
|
+
await ensureAuth();
|
|
99
|
+
return toolResult(await service.listRegions(params.first));
|
|
100
|
+
},
|
|
101
|
+
});
|
|
102
|
+
// ── Write ──────────────────────────────────────────────────
|
|
103
|
+
api.registerTool({
|
|
104
|
+
name: "kanvas_create_draft_order",
|
|
105
|
+
label: "Create Draft Order",
|
|
106
|
+
description: "Create a draft order. Requires email, customer (firstname), region_id, and at least one item with variant_id+quantity. Use kanvas_list_regions to get a region ID and kanvas_list_variants to find variants.",
|
|
107
|
+
parameters: Type.Object({
|
|
108
|
+
email: Type.String({ description: "Customer email" }),
|
|
109
|
+
phone: Type.Optional(Type.String()),
|
|
110
|
+
customer: OrderCustomerInput,
|
|
111
|
+
region_id: Type.Union([Type.String(), Type.Number()], { description: "Region ID (use kanvas_list_regions)" }),
|
|
112
|
+
items: Type.Array(OrderLineItemInput, { description: "Line items" }),
|
|
113
|
+
channel_id: Type.Optional(Type.Union([Type.String(), Type.Number()], { description: "Channel ID" })),
|
|
114
|
+
billing_address: Type.Optional(OrderBillingInput),
|
|
115
|
+
shipping_address: Type.Optional(OrderAddressInput),
|
|
116
|
+
note: Type.Optional(Type.String()),
|
|
117
|
+
metadata: Type.Optional(Type.Record(Type.String(), Type.Unknown())),
|
|
118
|
+
}),
|
|
119
|
+
async execute(_id, params) {
|
|
120
|
+
await ensureAuth();
|
|
121
|
+
return toolResult(await service.createDraftOrder(params));
|
|
122
|
+
},
|
|
123
|
+
});
|
|
124
|
+
api.registerTool({
|
|
125
|
+
name: "kanvas_update_order",
|
|
126
|
+
label: "Update Order",
|
|
127
|
+
description: "Update an order's items, fulfillment status, payment status, or metadata.",
|
|
128
|
+
parameters: Type.Object({
|
|
129
|
+
id: Type.String({ description: "Order ID" }),
|
|
130
|
+
items: Type.Optional(Type.Array(OrderLineItemInput)),
|
|
131
|
+
fulfillment_status: Type.Optional(Type.String()),
|
|
132
|
+
status: Type.Optional(Type.String()),
|
|
133
|
+
payment_status: Type.Optional(Type.String()),
|
|
134
|
+
metadata: Type.Optional(Type.Record(Type.String(), Type.Unknown())),
|
|
135
|
+
metadata_action: Type.Optional(Type.Union([Type.Literal("MERGE"), Type.Literal("REPLACE")])),
|
|
136
|
+
}),
|
|
137
|
+
async execute(_id, params) {
|
|
138
|
+
await ensureAuth();
|
|
139
|
+
const { id, ...input } = params;
|
|
140
|
+
return toolResult(await service.updateOrder(id, input));
|
|
141
|
+
},
|
|
142
|
+
});
|
|
143
|
+
api.registerTool({
|
|
144
|
+
name: "kanvas_update_draft_order_status",
|
|
145
|
+
label: "Update Draft Order Status",
|
|
146
|
+
description: "Change a draft order's status (PENDING, COMPLETED, DRAFT, CANCELED, FAILED).",
|
|
147
|
+
parameters: Type.Object({
|
|
148
|
+
order_id: Type.String({ description: "Order ID" }),
|
|
149
|
+
status: Type.Union([
|
|
150
|
+
Type.Literal("PENDING"),
|
|
151
|
+
Type.Literal("COMPLETED"),
|
|
152
|
+
Type.Literal("DRAFT"),
|
|
153
|
+
Type.Literal("CANCELED"),
|
|
154
|
+
Type.Literal("FAILED"),
|
|
155
|
+
], { description: "New status" }),
|
|
156
|
+
}),
|
|
157
|
+
async execute(_id, params) {
|
|
158
|
+
await ensureAuth();
|
|
159
|
+
return toolResult(await service.updateDraftOrderStatus(params.order_id, params.status));
|
|
160
|
+
},
|
|
161
|
+
});
|
|
162
|
+
api.registerTool({
|
|
163
|
+
name: "kanvas_transition_order_status",
|
|
164
|
+
label: "Transition Order Status",
|
|
165
|
+
description: "Move an order through its status pipeline using a status slug (from kanvas_list_order_statuses).",
|
|
166
|
+
parameters: Type.Object({
|
|
167
|
+
order_id: Type.String({ description: "Order ID" }),
|
|
168
|
+
status_slug: Type.Optional(Type.String({ description: "Target status slug" })),
|
|
169
|
+
date: Type.Optional(Type.String({ description: "Transition date" })),
|
|
170
|
+
}),
|
|
171
|
+
async execute(_id, params) {
|
|
172
|
+
await ensureAuth();
|
|
173
|
+
return toolResult(await service.transitionOrderStatus(params.order_id, params.status_slug, params.date));
|
|
174
|
+
},
|
|
175
|
+
});
|
|
176
|
+
api.registerTool({
|
|
177
|
+
name: "kanvas_order_change_customer",
|
|
178
|
+
label: "Change Order Customer",
|
|
179
|
+
description: "Change the customer on an order. Requires xKanvasKey (app-key authenticated).",
|
|
180
|
+
parameters: Type.Object({
|
|
181
|
+
order_id: Type.String({ description: "Order ID" }),
|
|
182
|
+
customer_id: Type.String({ description: "New customer ID" }),
|
|
183
|
+
}),
|
|
184
|
+
async execute(_id, params) {
|
|
185
|
+
await ensureAuth();
|
|
186
|
+
return toolResult(await service.changeOrderCustomer(params.order_id, params.customer_id));
|
|
187
|
+
},
|
|
188
|
+
});
|
|
189
|
+
api.registerTool({
|
|
190
|
+
name: "kanvas_delete_order",
|
|
191
|
+
label: "Delete Order",
|
|
192
|
+
description: "Delete an order.",
|
|
193
|
+
parameters: Type.Object({
|
|
194
|
+
id: Type.String({ description: "Order ID" }),
|
|
195
|
+
}),
|
|
196
|
+
async execute(_id, params) {
|
|
197
|
+
await ensureAuth();
|
|
198
|
+
return toolResult(await service.deleteOrder(params.id));
|
|
199
|
+
},
|
|
200
|
+
});
|
|
201
|
+
api.registerTool({
|
|
202
|
+
name: "kanvas_send_order_email",
|
|
203
|
+
label: "Send Order Email",
|
|
204
|
+
description: "Send an email for an order (confirmation, receipt, etc.). Requires xKanvasKey (app-key authenticated).",
|
|
205
|
+
parameters: Type.Object({
|
|
206
|
+
order_id: Type.String({ description: "Order ID" }),
|
|
207
|
+
template: Type.Optional(Type.String({ description: "Email template name" })),
|
|
208
|
+
}),
|
|
209
|
+
async execute(_id, params) {
|
|
210
|
+
await ensureAuth();
|
|
211
|
+
return toolResult(await service.sendOrderEmail(params.order_id, params.template));
|
|
212
|
+
},
|
|
213
|
+
});
|
|
29
214
|
}
|
package/package.json
CHANGED