@jskit-ai/workspaces-core 0.1.162 → 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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jskit-ai/workspaces-core",
3
- "version": "0.1.162",
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.184",
22
- "@jskit-ai/json-rest-api-core": "0.1.128",
23
- "@jskit-ai/resource-core": "0.1.126",
24
- "@jskit-ai/resource-crud-core": "0.1.126",
25
- "@jskit-ai/users-core": "0.1.197",
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.182",
173
- "@jskit-ai/http-runtime": "0.1.182",
174
- "@jskit-ai/kernel": "0.1.184"
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", () => {