@jskit-ai/workspaces-core 0.1.161 → 0.1.163
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/package.json +9 -9
- package/src/server/workspaceDirectory/workspaceDirectoryActions.js +36 -10
- package/src/server/workspaceMembers/workspaceMembersActions.js +55 -5
- package/src/server/workspacePendingInvitations/workspacePendingInvitationsActions.js +23 -0
- package/src/server/workspaceSettings/workspaceSettingsActions.js +14 -5
- package/src/shared/resources/workspaceAssistantOutputs.js +35 -0
- package/test/workspaceSettingsActions.test.js +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jskit-ai/workspaces-core",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.163",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"test": "node --test"
|
|
@@ -18,11 +18,11 @@
|
|
|
18
18
|
"./shared/resources/workspaceSettingsResource": "./src/shared/resources/workspaceSettingsResource.js"
|
|
19
19
|
},
|
|
20
20
|
"dependencies": {
|
|
21
|
-
"@jskit-ai/database-runtime": "0.1.
|
|
22
|
-
"@jskit-ai/json-rest-api-core": "0.1.
|
|
23
|
-
"@jskit-ai/resource-core": "0.1.
|
|
24
|
-
"@jskit-ai/resource-crud-core": "0.1.
|
|
25
|
-
"@jskit-ai/users-core": "0.1.
|
|
21
|
+
"@jskit-ai/database-runtime": "0.1.185",
|
|
22
|
+
"@jskit-ai/json-rest-api-core": "0.1.129",
|
|
23
|
+
"@jskit-ai/resource-core": "0.1.127",
|
|
24
|
+
"@jskit-ai/resource-crud-core": "0.1.127",
|
|
25
|
+
"@jskit-ai/users-core": "0.1.198",
|
|
26
26
|
"json-rest-schema": "^1.0.17"
|
|
27
27
|
},
|
|
28
28
|
"description": "Workspace tenancy runtime plus HTTP routes, role catalog, and workspace config scaffolding.",
|
|
@@ -169,8 +169,8 @@
|
|
|
169
169
|
}
|
|
170
170
|
},
|
|
171
171
|
"peerDependencies": {
|
|
172
|
-
"@jskit-ai/auth-core": "0.1.
|
|
173
|
-
"@jskit-ai/http-runtime": "0.1.
|
|
174
|
-
"@jskit-ai/kernel": "0.1.
|
|
172
|
+
"@jskit-ai/auth-core": "0.1.183",
|
|
173
|
+
"@jskit-ai/http-runtime": "0.1.183",
|
|
174
|
+
"@jskit-ai/kernel": "0.1.185"
|
|
175
175
|
}
|
|
176
176
|
}
|
|
@@ -8,6 +8,10 @@ import { workspaceResource } from "../../shared/resources/workspaceResource.js";
|
|
|
8
8
|
import { workspaceSlugParamsValidator } from "../common/validators/routeParamsValidator.js";
|
|
9
9
|
import { resolveActionUser } from "../common/support/resolveActionUser.js";
|
|
10
10
|
|
|
11
|
+
function workspaceAssistantSummary({ id, slug, name, ownerUserId, avatarUrl }) {
|
|
12
|
+
return { id, slug, name, ownerUserId, avatarUrl };
|
|
13
|
+
}
|
|
14
|
+
|
|
11
15
|
const workspaceUpdateInputValidator = composeSchemaDefinitions([
|
|
12
16
|
workspaceSlugParamsValidator,
|
|
13
17
|
workspaceResource.operations.patch.body
|
|
@@ -28,16 +32,18 @@ const workspaceDirectoryActionSpecifications = Object.freeze([
|
|
|
28
32
|
},
|
|
29
33
|
input: workspaceResource.operations.create.body,
|
|
30
34
|
output: null,
|
|
35
|
+
extensions: {
|
|
36
|
+
assistant: {
|
|
37
|
+
description: "Create a workspace for the signed-in user.",
|
|
38
|
+
output: workspaceResource.operations.create.output,
|
|
39
|
+
transformResult: (result) => workspaceAssistantSummary(result.value)
|
|
40
|
+
}
|
|
41
|
+
},
|
|
31
42
|
idempotency: "none",
|
|
32
43
|
audit: {
|
|
33
44
|
actionName: "workspace.workspaces.create"
|
|
34
45
|
},
|
|
35
46
|
observability: {},
|
|
36
|
-
extensions: {
|
|
37
|
-
assistant: {
|
|
38
|
-
description: "Create a workspace for the authenticated user."
|
|
39
|
-
}
|
|
40
|
-
},
|
|
41
47
|
async run(workspaceService, input, context) {
|
|
42
48
|
return returnJsonApiData(await workspaceService.createWorkspaceForAuthenticatedUser(resolveActionUser(context, input), input, {
|
|
43
49
|
request: resolveRequest(context),
|
|
@@ -56,6 +62,17 @@ const workspaceDirectoryActionSpecifications = Object.freeze([
|
|
|
56
62
|
},
|
|
57
63
|
input: emptyInputValidator,
|
|
58
64
|
output: null,
|
|
65
|
+
extensions: {
|
|
66
|
+
assistant: {
|
|
67
|
+
description: "List workspaces accessible to the signed-in user.",
|
|
68
|
+
output: workspaceResource.operations.list.output,
|
|
69
|
+
transformResult: (result) => ({
|
|
70
|
+
items: result.value.items.map(({ id, slug, name, avatarUrl, roleSid, isAccessible }) =>
|
|
71
|
+
({ id, slug, name, avatarUrl, roleSid, isAccessible })),
|
|
72
|
+
nextCursor: result.value.nextCursor
|
|
73
|
+
})
|
|
74
|
+
}
|
|
75
|
+
},
|
|
59
76
|
idempotency: "none",
|
|
60
77
|
audit: {
|
|
61
78
|
actionName: "workspace.workspaces.list"
|
|
@@ -83,6 +100,13 @@ const workspaceDirectoryActionSpecifications = Object.freeze([
|
|
|
83
100
|
},
|
|
84
101
|
input: workspaceSlugParamsValidator,
|
|
85
102
|
output: null,
|
|
103
|
+
extensions: {
|
|
104
|
+
assistant: {
|
|
105
|
+
description: "Read the active workspace profile.",
|
|
106
|
+
output: workspaceResource.operations.view.output,
|
|
107
|
+
transformResult: (result) => workspaceAssistantSummary(result.value)
|
|
108
|
+
}
|
|
109
|
+
},
|
|
86
110
|
idempotency: "none",
|
|
87
111
|
audit: {
|
|
88
112
|
actionName: "workspace.workspaces.read"
|
|
@@ -111,16 +135,18 @@ const workspaceDirectoryActionSpecifications = Object.freeze([
|
|
|
111
135
|
},
|
|
112
136
|
input: workspaceUpdateInputValidator,
|
|
113
137
|
output: null,
|
|
138
|
+
extensions: {
|
|
139
|
+
assistant: {
|
|
140
|
+
description: "Update the active workspace name or avatar URL.",
|
|
141
|
+
output: workspaceResource.operations.patch.output,
|
|
142
|
+
transformResult: (result) => workspaceAssistantSummary(result.value)
|
|
143
|
+
}
|
|
144
|
+
},
|
|
114
145
|
idempotency: "optional",
|
|
115
146
|
audit: {
|
|
116
147
|
actionName: "workspace.workspaces.update"
|
|
117
148
|
},
|
|
118
149
|
observability: {},
|
|
119
|
-
extensions: {
|
|
120
|
-
assistant: {
|
|
121
|
-
description: "Update workspace profile fields."
|
|
122
|
-
}
|
|
123
|
-
},
|
|
124
150
|
async run(workspaceService, input, context) {
|
|
125
151
|
const { workspaceSlug, ...patch } = input;
|
|
126
152
|
return returnJsonApiData(await workspaceService.updateWorkspaceForAuthenticatedUser(
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { workspaceInviteAssistantOutput } from "../../shared/resources/workspaceAssistantOutputs.js";
|
|
1
2
|
import { composeSchemaDefinitions } from "@jskit-ai/kernel/shared/validators";
|
|
2
3
|
import { returnJsonApiData } from "@jskit-ai/http-runtime/shared";
|
|
3
4
|
import { resolveWorkspace } from "../support/resolveWorkspace.js";
|
|
@@ -76,6 +77,13 @@ const workspaceMembersActionSpecifications = Object.freeze([
|
|
|
76
77
|
},
|
|
77
78
|
input: workspaceSlugParamsValidator,
|
|
78
79
|
output: null,
|
|
80
|
+
extensions: {
|
|
81
|
+
assistant: {
|
|
82
|
+
description: "List the active workspace roles and assignable permissions.",
|
|
83
|
+
output: workspaceMembersResource.operations.rolesList.output,
|
|
84
|
+
transformResult: (result) => result.value
|
|
85
|
+
}
|
|
86
|
+
},
|
|
79
87
|
idempotency: "none",
|
|
80
88
|
audit: {
|
|
81
89
|
actionName: "workspace.roles.list"
|
|
@@ -97,6 +105,13 @@ const workspaceMembersActionSpecifications = Object.freeze([
|
|
|
97
105
|
},
|
|
98
106
|
input: workspaceSlugParamsValidator,
|
|
99
107
|
output: null,
|
|
108
|
+
extensions: {
|
|
109
|
+
assistant: {
|
|
110
|
+
description: "List members of the active workspace.",
|
|
111
|
+
output: workspaceMembersResource.operations.membersList.output,
|
|
112
|
+
transformResult: (result) => result.value
|
|
113
|
+
}
|
|
114
|
+
},
|
|
100
115
|
idempotency: "none",
|
|
101
116
|
audit: {
|
|
102
117
|
actionName: "workspace.members.list"
|
|
@@ -120,6 +135,13 @@ const workspaceMembersActionSpecifications = Object.freeze([
|
|
|
120
135
|
},
|
|
121
136
|
input: updateMemberRoleActionInput,
|
|
122
137
|
output: null,
|
|
138
|
+
extensions: {
|
|
139
|
+
assistant: {
|
|
140
|
+
description: "Change a member’s role in the active workspace.",
|
|
141
|
+
output: workspaceMembersResource.operations.updateMemberRole.output,
|
|
142
|
+
transformResult: (result) => result.value
|
|
143
|
+
}
|
|
144
|
+
},
|
|
123
145
|
idempotency: "optional",
|
|
124
146
|
audit: {
|
|
125
147
|
actionName: "workspace.member.role.update"
|
|
@@ -147,6 +169,13 @@ const workspaceMembersActionSpecifications = Object.freeze([
|
|
|
147
169
|
},
|
|
148
170
|
input: removeMemberActionInput,
|
|
149
171
|
output: null,
|
|
172
|
+
extensions: {
|
|
173
|
+
assistant: {
|
|
174
|
+
description: "Remove a member from the active workspace.",
|
|
175
|
+
output: workspaceMembersResource.operations.removeMember.output,
|
|
176
|
+
transformResult: (result) => result.value
|
|
177
|
+
}
|
|
178
|
+
},
|
|
150
179
|
idempotency: "optional",
|
|
151
180
|
audit: {
|
|
152
181
|
actionName: "workspace.member.remove"
|
|
@@ -173,6 +202,13 @@ const workspaceMembersActionSpecifications = Object.freeze([
|
|
|
173
202
|
},
|
|
174
203
|
input: workspaceSlugParamsValidator,
|
|
175
204
|
output: null,
|
|
205
|
+
extensions: {
|
|
206
|
+
assistant: {
|
|
207
|
+
description: "List invitations for the active workspace without invitation tokens.",
|
|
208
|
+
output: workspaceMembersResource.operations.invitesList.output,
|
|
209
|
+
transformResult: (result) => result.value
|
|
210
|
+
}
|
|
211
|
+
},
|
|
176
212
|
idempotency: "none",
|
|
177
213
|
audit: {
|
|
178
214
|
actionName: "workspace.invites.list"
|
|
@@ -196,17 +232,24 @@ const workspaceMembersActionSpecifications = Object.freeze([
|
|
|
196
232
|
},
|
|
197
233
|
input: createInviteActionInput,
|
|
198
234
|
output: null,
|
|
235
|
+
extensions: {
|
|
236
|
+
assistant: {
|
|
237
|
+
description: "Invite a person to the active workspace and report delivery status without exposing invitation links.",
|
|
238
|
+
output: workspaceInviteAssistantOutput,
|
|
239
|
+
transformResult: (result) => ({
|
|
240
|
+
createdInviteId: result.value.createdInviteId,
|
|
241
|
+
invites: result.value.invites.map(({ id, email, roleSid, status, expiresAt }) =>
|
|
242
|
+
({ id, email, roleSid, status, expiresAt })),
|
|
243
|
+
deliveryStatus: result.value.inviteDelivery.status
|
|
244
|
+
})
|
|
245
|
+
}
|
|
246
|
+
},
|
|
199
247
|
idempotency: "optional",
|
|
200
248
|
audit: {
|
|
201
249
|
actionName: "workspace.invite.create"
|
|
202
250
|
},
|
|
203
251
|
observability: {},
|
|
204
252
|
events: WORKSPACE_INVITE_CREATED_EVENTS,
|
|
205
|
-
extensions: {
|
|
206
|
-
assistant: {
|
|
207
|
-
description: "Invite a person to the workspace."
|
|
208
|
-
}
|
|
209
|
-
},
|
|
210
253
|
async run(workspaceMembersService, input, context) {
|
|
211
254
|
return returnJsonApiData(await workspaceMembersService.createInvite(
|
|
212
255
|
resolveWorkspace(context, input),
|
|
@@ -233,6 +276,13 @@ const workspaceMembersActionSpecifications = Object.freeze([
|
|
|
233
276
|
},
|
|
234
277
|
input: revokeInviteActionInput,
|
|
235
278
|
output: null,
|
|
279
|
+
extensions: {
|
|
280
|
+
assistant: {
|
|
281
|
+
description: "Revoke an invitation to the active workspace.",
|
|
282
|
+
output: workspaceMembersResource.operations.revokeInvite.output,
|
|
283
|
+
transformResult: (result) => result.value
|
|
284
|
+
}
|
|
285
|
+
},
|
|
236
286
|
idempotency: "optional",
|
|
237
287
|
audit: {
|
|
238
288
|
actionName: "workspace.invite.revoke"
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { pendingInvitationsAssistantOutput } from "../../shared/resources/workspaceAssistantOutputs.js";
|
|
1
2
|
import {
|
|
2
3
|
emptyInputValidator
|
|
3
4
|
} from "@jskit-ai/kernel/shared/actions/actionContributorHelpers";
|
|
@@ -21,6 +22,11 @@ const workspacePendingInvitationsActionSpecifications = Object.freeze([
|
|
|
21
22
|
},
|
|
22
23
|
input: workspacePendingInvitationsResource.operations.resolve.query,
|
|
23
24
|
output: null,
|
|
25
|
+
extensions: {
|
|
26
|
+
assistant: {
|
|
27
|
+
exclude: "Use the invitation screen; raw invitation tokens must not enter assistant arguments."
|
|
28
|
+
}
|
|
29
|
+
},
|
|
24
30
|
idempotency: "none",
|
|
25
31
|
audit: {
|
|
26
32
|
actionName: "workspace.invitation.resolve"
|
|
@@ -45,6 +51,18 @@ const workspacePendingInvitationsActionSpecifications = Object.freeze([
|
|
|
45
51
|
},
|
|
46
52
|
input: emptyInputValidator,
|
|
47
53
|
output: null,
|
|
54
|
+
extensions: {
|
|
55
|
+
assistant: {
|
|
56
|
+
description: "List pending workspace invitations for the signed-in user without invitation tokens.",
|
|
57
|
+
output: pendingInvitationsAssistantOutput,
|
|
58
|
+
transformResult: (result) => ({
|
|
59
|
+
pendingInvites: result.value.pendingInvites.map(
|
|
60
|
+
({ id, workspaceId, workspaceSlug, workspaceName, roleSid, status, expiresAt }) =>
|
|
61
|
+
({ id, workspaceId, workspaceSlug, workspaceName, roleSid, status, expiresAt })
|
|
62
|
+
)
|
|
63
|
+
})
|
|
64
|
+
}
|
|
65
|
+
},
|
|
48
66
|
idempotency: "none",
|
|
49
67
|
audit: {
|
|
50
68
|
actionName: "workspace.invitations.pending.list"
|
|
@@ -69,6 +87,11 @@ const workspacePendingInvitationsActionSpecifications = Object.freeze([
|
|
|
69
87
|
},
|
|
70
88
|
input: workspaceMembersResource.operations.redeemInvite.body,
|
|
71
89
|
output: null,
|
|
90
|
+
extensions: {
|
|
91
|
+
assistant: {
|
|
92
|
+
exclude: "Use the authenticated invitation screen to accept or refuse; raw invitation tokens must not enter assistant arguments."
|
|
93
|
+
}
|
|
94
|
+
},
|
|
72
95
|
idempotency: "optional",
|
|
73
96
|
audit: {
|
|
74
97
|
actionName: "workspace.invite.redeem"
|
|
@@ -32,6 +32,13 @@ const workspaceSettingsActionSpecifications = Object.freeze([
|
|
|
32
32
|
},
|
|
33
33
|
input: workspaceSlugParamsValidator,
|
|
34
34
|
output: null,
|
|
35
|
+
extensions: {
|
|
36
|
+
assistant: {
|
|
37
|
+
description: "Read the active workspace appearance and invitation settings.",
|
|
38
|
+
output: workspaceSettingsResource.operations.view.output,
|
|
39
|
+
transformResult: (result) => result.value
|
|
40
|
+
}
|
|
41
|
+
},
|
|
35
42
|
idempotency: "none",
|
|
36
43
|
audit: {
|
|
37
44
|
actionName: "workspace.settings.read"
|
|
@@ -57,17 +64,19 @@ const workspaceSettingsActionSpecifications = Object.freeze([
|
|
|
57
64
|
},
|
|
58
65
|
input: workspaceSettingsUpdateInputValidator,
|
|
59
66
|
output: null,
|
|
67
|
+
extensions: {
|
|
68
|
+
assistant: {
|
|
69
|
+
description: "Update the active workspace appearance and invitation settings.",
|
|
70
|
+
output: workspaceSettingsResource.operations.patch.output,
|
|
71
|
+
transformResult: (result) => result.value
|
|
72
|
+
}
|
|
73
|
+
},
|
|
60
74
|
idempotency: "optional",
|
|
61
75
|
audit: {
|
|
62
76
|
actionName: "workspace.settings.update"
|
|
63
77
|
},
|
|
64
78
|
observability: {},
|
|
65
79
|
events: WORKSPACE_SETTINGS_CHANGED_EVENTS,
|
|
66
|
-
extensions: {
|
|
67
|
-
assistant: {
|
|
68
|
-
description: "Update workspace settings."
|
|
69
|
-
}
|
|
70
|
-
},
|
|
71
80
|
async run(workspaceSettingsService, input, context) {
|
|
72
81
|
const { workspaceSlug, ...patch } = input;
|
|
73
82
|
const response = await workspaceSettingsService.updateWorkspaceSettings(
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { createSchema } from "json-rest-schema";
|
|
2
|
+
import { createSchemaDefinition } from "@jskit-ai/resource-core/shared/resource";
|
|
3
|
+
|
|
4
|
+
// Deliberate assistant allowlists: HTTP invitation responses also contain credentials.
|
|
5
|
+
const workspaceInviteAssistantOutput = createSchemaDefinition(createSchema({
|
|
6
|
+
createdInviteId: { type: "string", required: true, minLength: 1 },
|
|
7
|
+
invites: {
|
|
8
|
+
type: "array", required: true,
|
|
9
|
+
items: createSchema({
|
|
10
|
+
id: { type: "string", required: true },
|
|
11
|
+
email: { type: "string", required: true },
|
|
12
|
+
roleSid: { type: "string", required: true },
|
|
13
|
+
status: { type: "string", required: true },
|
|
14
|
+
expiresAt: { type: "string", required: true }
|
|
15
|
+
})
|
|
16
|
+
},
|
|
17
|
+
deliveryStatus: { type: "string", required: true, enum: ["sent", "failed", "mailer_unconfigured"] }
|
|
18
|
+
}), "replace");
|
|
19
|
+
|
|
20
|
+
const pendingInvitationsAssistantOutput = createSchemaDefinition(createSchema({
|
|
21
|
+
pendingInvites: {
|
|
22
|
+
type: "array", required: true,
|
|
23
|
+
items: createSchema({
|
|
24
|
+
id: { type: "string", required: true },
|
|
25
|
+
workspaceId: { type: "string", required: true },
|
|
26
|
+
workspaceSlug: { type: "string", required: true },
|
|
27
|
+
workspaceName: { type: "string", required: true },
|
|
28
|
+
roleSid: { type: "string", required: true },
|
|
29
|
+
status: { type: "string", required: true },
|
|
30
|
+
expiresAt: { type: "string", required: false, nullable: true }
|
|
31
|
+
})
|
|
32
|
+
}
|
|
33
|
+
}), "replace");
|
|
34
|
+
|
|
35
|
+
export { workspaceInviteAssistantOutput, pendingInvitationsAssistantOutput };
|
|
@@ -13,7 +13,7 @@ test("workspace settings action specifications stay explicit", () => {
|
|
|
13
13
|
assert.deepEqual(workspaceSettingsActionSpecifications[0].surfaces, ["*"]);
|
|
14
14
|
assert.deepEqual(workspaceSettingsActionSpecifications[1].surfaces, ["*"]);
|
|
15
15
|
assert.deepEqual(workspaceSettingsActionSpecifications[1].channels, ["api", "assistant_tool", "automation", "internal"]);
|
|
16
|
-
assert.equal(workspaceSettingsActionSpecifications[1].extensions?.assistant?.description, "Update workspace settings.");
|
|
16
|
+
assert.equal(workspaceSettingsActionSpecifications[1].extensions?.assistant?.description, "Update the active workspace appearance and invitation settings.");
|
|
17
17
|
});
|
|
18
18
|
|
|
19
19
|
test("workspace actions array excludes workspace settings actions", () => {
|