@ekanos/cli 0.15.0 → 0.16.0

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.
Files changed (113) hide show
  1. package/README.md +41 -4
  2. package/dist/auth/ekanos-api.d.ts +23 -0
  3. package/dist/auth/ekanos-api.js +33 -6
  4. package/dist/auth/ekanos-api.js.map +1 -1
  5. package/dist/commands/agents.js +3 -2
  6. package/dist/commands/agents.js.map +1 -1
  7. package/dist/commands/apps.d.ts +11 -3
  8. package/dist/commands/apps.js +86 -28
  9. package/dist/commands/apps.js.map +1 -1
  10. package/dist/commands/catalog.d.ts +4 -2
  11. package/dist/commands/catalog.js +166 -35
  12. package/dist/commands/catalog.js.map +1 -1
  13. package/dist/commands/login.d.ts +2 -0
  14. package/dist/commands/login.js +17 -0
  15. package/dist/commands/login.js.map +1 -1
  16. package/dist/commands/runs.d.ts +7 -3
  17. package/dist/commands/runs.js +21 -5
  18. package/dist/commands/runs.js.map +1 -1
  19. package/dist/commands/scope-notice.d.ts +7 -0
  20. package/dist/commands/scope-notice.js +4 -11
  21. package/dist/commands/scope-notice.js.map +1 -1
  22. package/dist/commands/sources-roles.d.ts +5 -0
  23. package/dist/commands/sources-roles.js +235 -0
  24. package/dist/commands/sources-roles.js.map +1 -0
  25. package/dist/commands/sources.d.ts +5 -0
  26. package/dist/commands/sources.js +6 -1
  27. package/dist/commands/sources.js.map +1 -1
  28. package/dist/commands/team-agent-readiness.d.ts +18 -2
  29. package/dist/commands/team-agent-readiness.js +39 -39
  30. package/dist/commands/team-agent-readiness.js.map +1 -1
  31. package/dist/commands/team-agents-agents.d.ts +5 -2
  32. package/dist/commands/team-agents-agents.js +152 -15
  33. package/dist/commands/team-agents-agents.js.map +1 -1
  34. package/dist/commands/team-agents-define.d.ts +31 -0
  35. package/dist/commands/team-agents-define.js +176 -0
  36. package/dist/commands/team-agents-define.js.map +1 -0
  37. package/dist/commands/team-agents-mcp.js +112 -10
  38. package/dist/commands/team-agents-mcp.js.map +1 -1
  39. package/dist/commands/team-agents-triggers.d.ts +1 -1
  40. package/dist/commands/team-agents-triggers.js +137 -5
  41. package/dist/commands/team-agents-triggers.js.map +1 -1
  42. package/dist/commands/team-agents.d.ts +4 -1
  43. package/dist/commands/team-agents.js +17 -4
  44. package/dist/commands/team-agents.js.map +1 -1
  45. package/dist/commands/team-llm-key.d.ts +14 -0
  46. package/dist/commands/team-llm-key.js +122 -0
  47. package/dist/commands/team-llm-key.js.map +1 -0
  48. package/dist/commands/teams-connect.js +123 -31
  49. package/dist/commands/teams-connect.js.map +1 -1
  50. package/dist/commands/teams-lifecycle.d.ts +90 -0
  51. package/dist/commands/teams-lifecycle.js +457 -0
  52. package/dist/commands/teams-lifecycle.js.map +1 -0
  53. package/dist/commands/teams-onboard.d.ts +14 -0
  54. package/dist/commands/teams-onboard.js +62 -13
  55. package/dist/commands/teams-onboard.js.map +1 -1
  56. package/dist/commands/teams-overview.js +6 -2
  57. package/dist/commands/teams-overview.js.map +1 -1
  58. package/dist/commands/teams.d.ts +25 -5
  59. package/dist/commands/teams.js +101 -39
  60. package/dist/commands/teams.js.map +1 -1
  61. package/dist/commands/workflows.d.ts +37 -0
  62. package/dist/commands/workflows.js +589 -0
  63. package/dist/commands/workflows.js.map +1 -0
  64. package/dist/connect-fields.d.ts +22 -0
  65. package/dist/connect-fields.js +115 -0
  66. package/dist/connect-fields.js.map +1 -0
  67. package/dist/context.d.ts +12 -0
  68. package/dist/context.js +32 -9
  69. package/dist/context.js.map +1 -1
  70. package/dist/index.d.ts +13 -0
  71. package/dist/index.js +357 -122
  72. package/dist/index.js.map +1 -1
  73. package/dist/invocation.d.ts +31 -0
  74. package/dist/invocation.js +58 -0
  75. package/dist/invocation.js.map +1 -0
  76. package/dist/runs-api.js +8 -3
  77. package/dist/runs-api.js.map +1 -1
  78. package/dist/safe-fs.d.ts +18 -0
  79. package/dist/safe-fs.js +57 -0
  80. package/dist/safe-fs.js.map +1 -1
  81. package/dist/secret-form.d.ts +48 -0
  82. package/dist/secret-form.js +212 -0
  83. package/dist/secret-form.js.map +1 -0
  84. package/dist/secret-input.d.ts +96 -0
  85. package/dist/secret-input.js +299 -0
  86. package/dist/secret-input.js.map +1 -0
  87. package/dist/team-connect-api.d.ts +78 -3
  88. package/dist/team-connect-api.js +17 -2
  89. package/dist/team-connect-api.js.map +1 -1
  90. package/dist/team-lifecycle-api.d.ts +435 -0
  91. package/dist/team-lifecycle-api.js +301 -0
  92. package/dist/team-lifecycle-api.js.map +1 -0
  93. package/dist/teams-api.d.ts +13 -1
  94. package/dist/teams-api.js +88 -27
  95. package/dist/teams-api.js.map +1 -1
  96. package/dist/unknown-command.d.ts +18 -0
  97. package/dist/unknown-command.js +50 -0
  98. package/dist/unknown-command.js.map +1 -0
  99. package/dist/workflows-api.d.ts +69 -0
  100. package/dist/workflows-api.js +182 -0
  101. package/dist/workflows-api.js.map +1 -0
  102. package/package.json +3 -3
  103. package/templates/AGENTS.md.tmpl +6 -4
  104. package/templates/claude-skill.md.tmpl +4 -1
  105. package/templates/package.json.tmpl +4 -4
  106. package/templates/skills/build-agent/SKILL.md +43 -10
  107. package/templates/skills/build-agent/references/agent-json.md +4 -1
  108. package/templates/skills/build-agent/references/app-setup.md +14 -7
  109. package/templates/skills/build-agent/references/rollout.md +26 -2
  110. package/templates/skills/build-agent/references/set-up-an-integration.md +46 -29
  111. package/templates/skills/build-integration/references/widget-design.md +1 -1
  112. package/templates/skills/ekanos-platform/SKILL.md +66 -14
  113. package/templates/skills/polish-widgets/references/patterns.md +3 -3
@@ -0,0 +1,301 @@
1
+ import { z } from 'zod';
2
+ import { call } from './teams-api.js';
3
+ /**
4
+ * The CLI's client for a team's lifecycle and a Source's roles and people —
5
+ * every call a Source admin's, through `call` (`teams-api.ts`) for its
6
+ * refresh and refusals.
7
+ *
8
+ * POST /api/partner/teams/<team>/members/<email>/resend → resend | renew
9
+ * POST /api/partner/teams/<team>/leave → the caller leaves
10
+ * GET|POST /api/partner/teams/<team>/groups
11
+ * PATCH|DELETE /api/partner/teams/<team>/groups/<group>
12
+ * PUT|DELETE /api/partner/teams/<team>/groups/<group>/members/<email>
13
+ * GET /api/partner/teams/<team>/health
14
+ * POST /api/partner/teams/<team>/health/<product> → run now
15
+ * GET /api/partner/teams/<team>/workspaces
16
+ * PUT /api/partner/teams/<team>/workspaces/default { workspace }
17
+ * GET|POST /api/partner/sources/roles
18
+ * PATCH|DELETE /api/partner/sources/roles/<role>
19
+ * GET /api/partner/sources/people[?search=&page=]
20
+ *
21
+ * The shapes are read here rather than from `@ekanos/integration-schema`, so
22
+ * this CLI works against a host without a schema release.
23
+ */
24
+ const SourceRefSchema = z.object({
25
+ id: z.string(),
26
+ slug: z.string(),
27
+ name: z.string().nullable(),
28
+ });
29
+ const TeamRefSchema = z.object({ slug: z.string(), name: z.string() });
30
+ const PersonSchema = z.object({
31
+ userId: z.string(),
32
+ email: z.string().nullable(),
33
+ name: z.string().nullable(),
34
+ });
35
+ export const InvitationResendSchema = z.object({
36
+ team: TeamRefSchema,
37
+ email: z.string(),
38
+ role: z.string(),
39
+ action: z.enum(['renewed', 'resent']),
40
+ expiresAt: z.string(),
41
+ });
42
+ export const TeamLeaveSchema = z.object({
43
+ team: TeamRefSchema,
44
+ role: z.string(),
45
+ });
46
+ export const TeamGroupSchema = z.object({
47
+ id: z.string(),
48
+ name: z.string(),
49
+ description: z.string().nullable(),
50
+ members: z.array(PersonSchema),
51
+ products: z.array(z.object({ slug: z.string(), name: z.string() })),
52
+ widgetCount: z.number(),
53
+ mcpToolCount: z.number(),
54
+ });
55
+ const GroupListSchema = z.object({
56
+ source: SourceRefSchema,
57
+ team: TeamRefSchema,
58
+ groups: z.array(TeamGroupSchema),
59
+ });
60
+ const GroupResultSchema = z.object({
61
+ team: TeamRefSchema,
62
+ group: TeamGroupSchema,
63
+ });
64
+ const GroupUpdateSchema = GroupResultSchema.extend({
65
+ previous: TeamGroupSchema,
66
+ });
67
+ const GroupMemberSchema = GroupResultSchema.extend({
68
+ email: z.string(),
69
+ changed: z.boolean(),
70
+ });
71
+ const HealthStatusSchema = z.enum([
72
+ 'healthy',
73
+ 'degraded',
74
+ 'unhealthy',
75
+ 'unknown',
76
+ ]);
77
+ export const TeamHealthRowSchema = z.object({
78
+ productId: z.string(),
79
+ productName: z.string(),
80
+ slug: z.string(),
81
+ status: HealthStatusSchema,
82
+ lastCheckedAt: z.string().nullable(),
83
+ lastSuccessAt: z.string().nullable(),
84
+ lastFailureAt: z.string().nullable(),
85
+ lastErrorMessage: z.string().nullable(),
86
+ errorRatePct: z.number().nullable(),
87
+ tokenExpiresAt: z.string().nullable(),
88
+ statusReason: z.string().nullable(),
89
+ });
90
+ const HealthListSchema = z.object({
91
+ source: SourceRefSchema,
92
+ team: TeamRefSchema,
93
+ integrations: z.array(TeamHealthRowSchema),
94
+ });
95
+ const HealthRunSchema = z.object({
96
+ team: TeamRefSchema,
97
+ integration: TeamHealthRowSchema,
98
+ });
99
+ const WorkspaceSchema = z.object({
100
+ slug: z.string(),
101
+ name: z.string(),
102
+ label: z.string().nullable(),
103
+ visible: z.boolean(),
104
+ isDefault: z.boolean(),
105
+ });
106
+ const WorkspaceListSchema = z.object({
107
+ source: SourceRefSchema,
108
+ team: TeamRefSchema,
109
+ workspaces: z.array(WorkspaceSchema),
110
+ });
111
+ const WorkspaceDefaultSchema = z.object({
112
+ team: TeamRefSchema,
113
+ workspace: WorkspaceSchema,
114
+ previous: WorkspaceSchema.nullable(),
115
+ changed: z.boolean(),
116
+ });
117
+ export const SourceRoleSchema = z.object({
118
+ name: z.string(),
119
+ displayName: z.string(),
120
+ description: z.string().nullable(),
121
+ hierarchyLevel: z.number(),
122
+ isSystem: z.boolean(),
123
+ permissions: z.array(z.string()),
124
+ memberCount: z.number(),
125
+ });
126
+ const RoleListSchema = z.object({
127
+ source: SourceRefSchema,
128
+ roles: z.array(SourceRoleSchema),
129
+ permissions: z.array(z.object({
130
+ permission: z.string(),
131
+ label: z.string(),
132
+ category: z.string(),
133
+ })),
134
+ });
135
+ const RoleResultSchema = z.object({
136
+ source: SourceRefSchema,
137
+ role: SourceRoleSchema,
138
+ });
139
+ const RoleUpdateSchema = RoleResultSchema.extend({
140
+ previous: SourceRoleSchema,
141
+ });
142
+ const PersonStateSchema = z.enum([
143
+ 'active',
144
+ 'suspended',
145
+ 'invited',
146
+ 'left',
147
+ 'removed',
148
+ ]);
149
+ const PeopleSchema = z.object({
150
+ source: SourceRefSchema,
151
+ people: z.array(z.object({
152
+ userId: z.string(),
153
+ name: z.string().nullable(),
154
+ email: z.string().nullable(),
155
+ joinedAt: z.string().nullable(),
156
+ status: PersonStateSchema,
157
+ teams: z.array(z.object({
158
+ accountName: z.string(),
159
+ roleLabel: z.string(),
160
+ status: PersonStateSchema,
161
+ })),
162
+ })),
163
+ total: z.number(),
164
+ page: z.number(),
165
+ pageSize: z.number(),
166
+ });
167
+ const teamPath = (team) => `/api/partner/teams/${encodeURIComponent(team)}`;
168
+ const memberPath = (team, email) => `${teamPath(team)}/members/${encodeURIComponent(email)}`;
169
+ const groupPath = (team, group) => `${teamPath(team)}/groups/${encodeURIComponent(group)}`;
170
+ export function resendTeamInvitation(host, token, target) {
171
+ return call(host, token, InvitationResendSchema, {
172
+ method: 'POST',
173
+ path: `${memberPath(target.team, target.email)}/resend`,
174
+ source: target.source,
175
+ });
176
+ }
177
+ export function leaveTeam(host, token, target) {
178
+ return call(host, token, TeamLeaveSchema, {
179
+ method: 'POST',
180
+ path: `${teamPath(target.team)}/leave`,
181
+ source: target.source,
182
+ });
183
+ }
184
+ export function listTeamGroups(host, token, target) {
185
+ return call(host, token, GroupListSchema, {
186
+ method: 'GET',
187
+ path: `${teamPath(target.team)}/groups`,
188
+ source: target.source,
189
+ });
190
+ }
191
+ export function createTeamGroup(host, token, target, body) {
192
+ return call(host, token, GroupResultSchema, {
193
+ method: 'POST',
194
+ path: `${teamPath(target.team)}/groups`,
195
+ source: target.source,
196
+ body,
197
+ });
198
+ }
199
+ export function updateTeamGroup(host, token, target, body) {
200
+ return call(host, token, GroupUpdateSchema, {
201
+ method: 'PATCH',
202
+ path: groupPath(target.team, target.group),
203
+ source: target.source,
204
+ body,
205
+ });
206
+ }
207
+ export function deleteTeamGroup(host, token, target) {
208
+ return call(host, token, GroupResultSchema, {
209
+ method: 'DELETE',
210
+ path: groupPath(target.team, target.group),
211
+ source: target.source,
212
+ });
213
+ }
214
+ export function setTeamGroupMember(host, token, target, member) {
215
+ return call(host, token, GroupMemberSchema, {
216
+ method: member ? 'PUT' : 'DELETE',
217
+ path: `${groupPath(target.team, target.group)}/members/${encodeURIComponent(target.email)}`,
218
+ source: target.source,
219
+ });
220
+ }
221
+ export function listTeamHealth(host, token, target) {
222
+ return call(host, token, HealthListSchema, {
223
+ method: 'GET',
224
+ path: `${teamPath(target.team)}/health`,
225
+ source: target.source,
226
+ });
227
+ }
228
+ /** The caller's own personal connection's health; `run` checks it now. */
229
+ export function ownTeamHealth(host, token, target, run) {
230
+ return call(host, token, HealthRunSchema, {
231
+ method: run ? 'POST' : 'GET',
232
+ path: `${teamPath(target.team)}/health/${encodeURIComponent(target.product)}/mine`,
233
+ source: target.source,
234
+ });
235
+ }
236
+ export function runTeamHealthCheck(host, token, target) {
237
+ return call(host, token, HealthRunSchema, {
238
+ method: 'POST',
239
+ path: `${teamPath(target.team)}/health/${encodeURIComponent(target.product)}`,
240
+ source: target.source,
241
+ });
242
+ }
243
+ export function listTeamWorkspaces(host, token, target) {
244
+ return call(host, token, WorkspaceListSchema, {
245
+ method: 'GET',
246
+ path: `${teamPath(target.team)}/workspaces`,
247
+ source: target.source,
248
+ });
249
+ }
250
+ export function setTeamDefaultWorkspace(host, token, target, workspace) {
251
+ return call(host, token, WorkspaceDefaultSchema, {
252
+ method: 'PUT',
253
+ path: `${teamPath(target.team)}/workspaces/default`,
254
+ source: target.source,
255
+ body: { workspace },
256
+ });
257
+ }
258
+ export function listSourceRoles(host, token, source) {
259
+ return call(host, token, RoleListSchema, {
260
+ method: 'GET',
261
+ path: '/api/partner/sources/roles',
262
+ source,
263
+ });
264
+ }
265
+ export function createSourceRole(host, token, source, body) {
266
+ return call(host, token, RoleResultSchema, {
267
+ method: 'POST',
268
+ path: '/api/partner/sources/roles',
269
+ source,
270
+ body,
271
+ });
272
+ }
273
+ export function updateSourceRole(host, token, target, body) {
274
+ return call(host, token, RoleUpdateSchema, {
275
+ method: 'PATCH',
276
+ path: `/api/partner/sources/roles/${encodeURIComponent(target.role)}`,
277
+ source: target.source,
278
+ body,
279
+ });
280
+ }
281
+ export function deleteSourceRole(host, token, target) {
282
+ return call(host, token, RoleResultSchema, {
283
+ method: 'DELETE',
284
+ path: `/api/partner/sources/roles/${encodeURIComponent(target.role)}`,
285
+ source: target.source,
286
+ });
287
+ }
288
+ export function listSourcePeople(host, token, source, query) {
289
+ const params = new URLSearchParams();
290
+ if (query.search)
291
+ params.set('search', query.search);
292
+ if (query.page !== undefined)
293
+ params.set('page', String(query.page));
294
+ const encoded = params.toString();
295
+ return call(host, token, PeopleSchema, {
296
+ method: 'GET',
297
+ path: `/api/partner/sources/people${encoded ? `?${encoded}` : ''}`,
298
+ source,
299
+ });
300
+ }
301
+ //# sourceMappingURL=team-lifecycle-api.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"team-lifecycle-api.js","sourceRoot":"","sources":["../src/team-lifecycle-api.ts"],"names":[],"mappings":"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","sourcesContent":["import { z } from 'zod';\n\nimport { type TeamsApiResult, call } from './teams-api';\n\n/**\n * The CLI's client for a team's lifecycle and a Source's roles and people —\n * every call a Source admin's, through `call` (`teams-api.ts`) for its\n * refresh and refusals.\n *\n * POST /api/partner/teams/<team>/members/<email>/resend → resend | renew\n * POST /api/partner/teams/<team>/leave → the caller leaves\n * GET|POST /api/partner/teams/<team>/groups\n * PATCH|DELETE /api/partner/teams/<team>/groups/<group>\n * PUT|DELETE /api/partner/teams/<team>/groups/<group>/members/<email>\n * GET /api/partner/teams/<team>/health\n * POST /api/partner/teams/<team>/health/<product> → run now\n * GET /api/partner/teams/<team>/workspaces\n * PUT /api/partner/teams/<team>/workspaces/default { workspace }\n * GET|POST /api/partner/sources/roles\n * PATCH|DELETE /api/partner/sources/roles/<role>\n * GET /api/partner/sources/people[?search=&page=]\n *\n * The shapes are read here rather than from `@ekanos/integration-schema`, so\n * this CLI works against a host without a schema release.\n */\n\nconst SourceRefSchema = z.object({\n id: z.string(),\n slug: z.string(),\n name: z.string().nullable(),\n});\nconst TeamRefSchema = z.object({ slug: z.string(), name: z.string() });\nconst PersonSchema = z.object({\n userId: z.string(),\n email: z.string().nullable(),\n name: z.string().nullable(),\n});\n\nexport const InvitationResendSchema = z.object({\n team: TeamRefSchema,\n email: z.string(),\n role: z.string(),\n action: z.enum(['renewed', 'resent']),\n expiresAt: z.string(),\n});\n\nexport const TeamLeaveSchema = z.object({\n team: TeamRefSchema,\n role: z.string(),\n});\n\nexport const TeamGroupSchema = z.object({\n id: z.string(),\n name: z.string(),\n description: z.string().nullable(),\n members: z.array(PersonSchema),\n products: z.array(z.object({ slug: z.string(), name: z.string() })),\n widgetCount: z.number(),\n mcpToolCount: z.number(),\n});\nexport type TeamGroup = z.infer<typeof TeamGroupSchema>;\n\nconst GroupListSchema = z.object({\n source: SourceRefSchema,\n team: TeamRefSchema,\n groups: z.array(TeamGroupSchema),\n});\nconst GroupResultSchema = z.object({\n team: TeamRefSchema,\n group: TeamGroupSchema,\n});\nconst GroupUpdateSchema = GroupResultSchema.extend({\n previous: TeamGroupSchema,\n});\nconst GroupMemberSchema = GroupResultSchema.extend({\n email: z.string(),\n changed: z.boolean(),\n});\n\nconst HealthStatusSchema = z.enum([\n 'healthy',\n 'degraded',\n 'unhealthy',\n 'unknown',\n]);\nexport const TeamHealthRowSchema = z.object({\n productId: z.string(),\n productName: z.string(),\n slug: z.string(),\n status: HealthStatusSchema,\n lastCheckedAt: z.string().nullable(),\n lastSuccessAt: z.string().nullable(),\n lastFailureAt: z.string().nullable(),\n lastErrorMessage: z.string().nullable(),\n errorRatePct: z.number().nullable(),\n tokenExpiresAt: z.string().nullable(),\n statusReason: z.string().nullable(),\n});\nexport type TeamHealthRow = z.infer<typeof TeamHealthRowSchema>;\n\nconst HealthListSchema = z.object({\n source: SourceRefSchema,\n team: TeamRefSchema,\n integrations: z.array(TeamHealthRowSchema),\n});\nconst HealthRunSchema = z.object({\n team: TeamRefSchema,\n integration: TeamHealthRowSchema,\n});\n\nconst WorkspaceSchema = z.object({\n slug: z.string(),\n name: z.string(),\n label: z.string().nullable(),\n visible: z.boolean(),\n isDefault: z.boolean(),\n});\nconst WorkspaceListSchema = z.object({\n source: SourceRefSchema,\n team: TeamRefSchema,\n workspaces: z.array(WorkspaceSchema),\n});\nconst WorkspaceDefaultSchema = z.object({\n team: TeamRefSchema,\n workspace: WorkspaceSchema,\n previous: WorkspaceSchema.nullable(),\n changed: z.boolean(),\n});\n\nexport const SourceRoleSchema = z.object({\n name: z.string(),\n displayName: z.string(),\n description: z.string().nullable(),\n hierarchyLevel: z.number(),\n isSystem: z.boolean(),\n permissions: z.array(z.string()),\n memberCount: z.number(),\n});\nexport type SourceRole = z.infer<typeof SourceRoleSchema>;\n\nconst RoleListSchema = z.object({\n source: SourceRefSchema,\n roles: z.array(SourceRoleSchema),\n permissions: z.array(\n z.object({\n permission: z.string(),\n label: z.string(),\n category: z.string(),\n }),\n ),\n});\nconst RoleResultSchema = z.object({\n source: SourceRefSchema,\n role: SourceRoleSchema,\n});\nconst RoleUpdateSchema = RoleResultSchema.extend({\n previous: SourceRoleSchema,\n});\n\nconst PersonStateSchema = z.enum([\n 'active',\n 'suspended',\n 'invited',\n 'left',\n 'removed',\n]);\nconst PeopleSchema = z.object({\n source: SourceRefSchema,\n people: z.array(\n z.object({\n userId: z.string(),\n name: z.string().nullable(),\n email: z.string().nullable(),\n joinedAt: z.string().nullable(),\n status: PersonStateSchema,\n teams: z.array(\n z.object({\n accountName: z.string(),\n roleLabel: z.string(),\n status: PersonStateSchema,\n }),\n ),\n }),\n ),\n total: z.number(),\n page: z.number(),\n pageSize: z.number(),\n});\nexport type SourcePeople = z.infer<typeof PeopleSchema>;\n\ntype TeamTarget = { source: string; team: string };\ntype Api<T> = Promise<TeamsApiResult<T>>;\n\nconst teamPath = (team: string) =>\n `/api/partner/teams/${encodeURIComponent(team)}`;\nconst memberPath = (team: string, email: string) =>\n `${teamPath(team)}/members/${encodeURIComponent(email)}`;\nconst groupPath = (team: string, group: string) =>\n `${teamPath(team)}/groups/${encodeURIComponent(group)}`;\n\nexport function resendTeamInvitation(\n host: string,\n token: string,\n target: TeamTarget & { email: string },\n): Api<z.infer<typeof InvitationResendSchema>> {\n return call(host, token, InvitationResendSchema, {\n method: 'POST',\n path: `${memberPath(target.team, target.email)}/resend`,\n source: target.source,\n });\n}\n\nexport function leaveTeam(\n host: string,\n token: string,\n target: TeamTarget,\n): Api<z.infer<typeof TeamLeaveSchema>> {\n return call(host, token, TeamLeaveSchema, {\n method: 'POST',\n path: `${teamPath(target.team)}/leave`,\n source: target.source,\n });\n}\n\nexport function listTeamGroups(\n host: string,\n token: string,\n target: TeamTarget,\n): Api<z.infer<typeof GroupListSchema>> {\n return call(host, token, GroupListSchema, {\n method: 'GET',\n path: `${teamPath(target.team)}/groups`,\n source: target.source,\n });\n}\n\nexport function createTeamGroup(\n host: string,\n token: string,\n target: TeamTarget,\n body: { name: string; description?: string; products?: string[] },\n): Api<z.infer<typeof GroupResultSchema>> {\n return call(host, token, GroupResultSchema, {\n method: 'POST',\n path: `${teamPath(target.team)}/groups`,\n source: target.source,\n body,\n });\n}\n\nexport function updateTeamGroup(\n host: string,\n token: string,\n target: TeamTarget & { group: string },\n body: { name?: string; description?: string | null; products?: string[] },\n): Api<z.infer<typeof GroupUpdateSchema>> {\n return call(host, token, GroupUpdateSchema, {\n method: 'PATCH',\n path: groupPath(target.team, target.group),\n source: target.source,\n body,\n });\n}\n\nexport function deleteTeamGroup(\n host: string,\n token: string,\n target: TeamTarget & { group: string },\n): Api<z.infer<typeof GroupResultSchema>> {\n return call(host, token, GroupResultSchema, {\n method: 'DELETE',\n path: groupPath(target.team, target.group),\n source: target.source,\n });\n}\n\nexport function setTeamGroupMember(\n host: string,\n token: string,\n target: TeamTarget & { group: string; email: string },\n member: boolean,\n): Api<z.infer<typeof GroupMemberSchema>> {\n return call(host, token, GroupMemberSchema, {\n method: member ? 'PUT' : 'DELETE',\n path: `${groupPath(target.team, target.group)}/members/${encodeURIComponent(target.email)}`,\n source: target.source,\n });\n}\n\nexport function listTeamHealth(\n host: string,\n token: string,\n target: TeamTarget,\n): Api<z.infer<typeof HealthListSchema>> {\n return call(host, token, HealthListSchema, {\n method: 'GET',\n path: `${teamPath(target.team)}/health`,\n source: target.source,\n });\n}\n\n/** The caller's own personal connection's health; `run` checks it now. */\nexport function ownTeamHealth(\n host: string,\n token: string,\n target: TeamTarget & { product: string },\n run: boolean,\n): Api<z.infer<typeof HealthRunSchema>> {\n return call(host, token, HealthRunSchema, {\n method: run ? 'POST' : 'GET',\n path: `${teamPath(target.team)}/health/${encodeURIComponent(target.product)}/mine`,\n source: target.source,\n });\n}\n\nexport function runTeamHealthCheck(\n host: string,\n token: string,\n target: TeamTarget & { product: string },\n): Api<z.infer<typeof HealthRunSchema>> {\n return call(host, token, HealthRunSchema, {\n method: 'POST',\n path: `${teamPath(target.team)}/health/${encodeURIComponent(target.product)}`,\n source: target.source,\n });\n}\n\nexport function listTeamWorkspaces(\n host: string,\n token: string,\n target: TeamTarget,\n): Api<z.infer<typeof WorkspaceListSchema>> {\n return call(host, token, WorkspaceListSchema, {\n method: 'GET',\n path: `${teamPath(target.team)}/workspaces`,\n source: target.source,\n });\n}\n\nexport function setTeamDefaultWorkspace(\n host: string,\n token: string,\n target: TeamTarget,\n workspace: string,\n): Api<z.infer<typeof WorkspaceDefaultSchema>> {\n return call(host, token, WorkspaceDefaultSchema, {\n method: 'PUT',\n path: `${teamPath(target.team)}/workspaces/default`,\n source: target.source,\n body: { workspace },\n });\n}\n\nexport function listSourceRoles(\n host: string,\n token: string,\n source: string,\n): Api<z.infer<typeof RoleListSchema>> {\n return call(host, token, RoleListSchema, {\n method: 'GET',\n path: '/api/partner/sources/roles',\n source,\n });\n}\n\nexport function createSourceRole(\n host: string,\n token: string,\n source: string,\n body: {\n name: string;\n displayName: string;\n description?: string;\n hierarchyLevel: number;\n permissions: string[];\n },\n): Api<z.infer<typeof RoleResultSchema>> {\n return call(host, token, RoleResultSchema, {\n method: 'POST',\n path: '/api/partner/sources/roles',\n source,\n body,\n });\n}\n\nexport function updateSourceRole(\n host: string,\n token: string,\n target: { source: string; role: string },\n body: {\n displayName?: string;\n description?: string;\n hierarchyLevel?: number;\n permissions?: string[];\n grant?: string[];\n revoke?: string[];\n },\n): Api<z.infer<typeof RoleUpdateSchema>> {\n return call(host, token, RoleUpdateSchema, {\n method: 'PATCH',\n path: `/api/partner/sources/roles/${encodeURIComponent(target.role)}`,\n source: target.source,\n body,\n });\n}\n\nexport function deleteSourceRole(\n host: string,\n token: string,\n target: { source: string; role: string },\n): Api<z.infer<typeof RoleResultSchema>> {\n return call(host, token, RoleResultSchema, {\n method: 'DELETE',\n path: `/api/partner/sources/roles/${encodeURIComponent(target.role)}`,\n source: target.source,\n });\n}\n\nexport function listSourcePeople(\n host: string,\n token: string,\n source: string,\n query: { search?: string; page?: number },\n): Api<SourcePeople> {\n const params = new URLSearchParams();\n if (query.search) params.set('search', query.search);\n if (query.page !== undefined) params.set('page', String(query.page));\n const encoded = params.toString();\n return call(host, token, PeopleSchema, {\n method: 'GET',\n path: `/api/partner/sources/people${encoded ? `?${encoded}` : ''}`,\n source,\n });\n}\n"]}
@@ -1,4 +1,4 @@
1
- import { type ProductScopeList, type ProductScopeProductChange, type TeamScopes, type TeamScopesSetResult, type TeamAppSetResult, type TeamCreateRequest, type TeamCreateResult, type TeamDisconnectResult, type TeamMemberChangeResult, type TeamMemberInviteResult, type TeamMemberList, type TeamRenameResult, type TeamRoles, type TeamIntegrationStatus, type TeamIntegrationEventList, type TeamList, type TeamWebhookMintResult } from '@ekanos/integration-schema';
1
+ import { type ProductScopeList, type ProductScopeProductChange, type TeamScopes, type TeamScopesSetResult, type TeamAppSetResult, type TeamCreateRequest, type TeamCreateResult, type TeamDisconnectResult, type TeamMemberChangeResult, type TeamMemberAddResult, type TeamMemberInviteResult, type TeamMemberList, type TeamRenameResult, type TeamRoles, type TeamIntegrationStatus, type TeamIntegrationEventList, type TeamList, type TeamWebhookMintResult } from '@ekanos/integration-schema';
2
2
  import type { z } from 'zod';
3
3
  /**
4
4
  * The CLI's client for a Source's teams and their integration setup — the
@@ -64,6 +64,7 @@ export declare function disconnectTeamIntegration(host: string, accessToken: str
64
64
  source: string;
65
65
  team: string;
66
66
  product: string;
67
+ mine?: boolean;
67
68
  }): Promise<TeamsApiResult<TeamDisconnectResult>>;
68
69
  export declare function createTeam(host: string, accessToken: string, source: string, body: TeamCreateRequest): Promise<TeamsApiResult<TeamCreateResult>>;
69
70
  export declare function renameTeam(host: string, accessToken: string, target: {
@@ -81,6 +82,17 @@ export declare function inviteTeamMember(host: string, accessToken: string, targ
81
82
  email: string;
82
83
  role: string;
83
84
  }): Promise<TeamsApiResult<TeamMemberInviteResult>>;
85
+ /** `teams members add`: a member now, no invitation email (`PUT`). */
86
+ export declare function addTeamMember(host: string, accessToken: string, target: {
87
+ source: string;
88
+ team: string;
89
+ }, body: {
90
+ self: true;
91
+ role?: string;
92
+ } | {
93
+ email: string;
94
+ role?: string;
95
+ }): Promise<TeamsApiResult<TeamMemberAddResult>>;
84
96
  export declare function setTeamMemberRole(host: string, accessToken: string, target: {
85
97
  source: string;
86
98
  team: string;
package/dist/teams-api.js CHANGED
@@ -1,4 +1,4 @@
1
- import { ProductScopeListSchema, ProductScopeProductChangeSchema, TeamScopesSchema, TeamScopesSetResultSchema, TeamAppSetResultSchema, TeamCreateResultSchema, TeamDisconnectResultSchema, TeamMemberChangeResultSchema, TeamMemberInviteResultSchema, TeamMemberListSchema, TeamRenameResultSchema, TeamRolesSchema, TeamIntegrationStatusSchema, TeamIntegrationEventListSchema, TeamListSchema, TeamWebhookMintResultSchema, } from '@ekanos/integration-schema';
1
+ import { ProductScopeListSchema, ProductScopeProductChangeSchema, TeamScopesSchema, TeamScopesSetResultSchema, TeamAppSetResultSchema, TeamCreateResultSchema, TeamDisconnectResultSchema, TeamMemberChangeResultSchema, TeamMemberAddResultSchema, TeamMemberInviteResultSchema, TeamMemberListSchema, TeamRenameResultSchema, TeamRolesSchema, TeamIntegrationStatusSchema, TeamIntegrationEventListSchema, TeamListSchema, TeamWebhookMintResultSchema, } from '@ekanos/integration-schema';
2
2
  import { request } from './auth/ekanos-api.js';
3
3
  import { authRequiredError, forbiddenError, invalidStateError, networkError, notFoundError, usageError, validationError, } from './errors.js';
4
4
  export function listTeams(host, accessToken, source) {
@@ -33,7 +33,8 @@ export function mintTeamWebhook(host, accessToken, target, webhookId) {
33
33
  export function disconnectTeamIntegration(host, accessToken, target) {
34
34
  return call(host, accessToken, TeamDisconnectResultSchema, {
35
35
  method: 'DELETE',
36
- path: integrationPath(target),
36
+ // `--mine`: the caller's own personal connection, never another's.
37
+ path: `${integrationPath(target)}${target.mine ? '/mine' : ''}`,
37
38
  source: target.source,
38
39
  });
39
40
  }
@@ -68,6 +69,15 @@ export function inviteTeamMember(host, accessToken, target, body) {
68
69
  body,
69
70
  });
70
71
  }
72
+ /** `teams members add`: a member now, no invitation email (`PUT`). */
73
+ export function addTeamMember(host, accessToken, target, body) {
74
+ return call(host, accessToken, TeamMemberAddResultSchema, {
75
+ method: 'PUT',
76
+ path: membersPath(target.team),
77
+ source: target.source,
78
+ body,
79
+ });
80
+ }
71
81
  export function setTeamMemberRole(host, accessToken, target, role) {
72
82
  return call(host, accessToken, TeamMemberChangeResultSchema, {
73
83
  method: 'PATCH',
@@ -143,6 +153,7 @@ function integrationPath(target) {
143
153
  }
144
154
  /** One partner teams call; shared by the team-agent clients (`team-agents-api.ts`). */
145
155
  export async function call(host, accessToken, schema, init) {
156
+ var _a, _b;
146
157
  const response = await request(`${host}${init.path}${init.path.includes('?') ? '&' : '?'}${new URLSearchParams({ source: init.source })}`, {
147
158
  method: init.method,
148
159
  headers: Object.assign({ accept: 'application/json', authorization: `Bearer ${accessToken}` }, (init.body === undefined
@@ -165,10 +176,18 @@ export async function call(host, accessToken, schema, init) {
165
176
  ? "Only a Source admin manages its teams' integrations. Ask one to run it."
166
177
  : code === 'CONFIRM_NOT_PERMITTED'
167
178
  ? "Only a Source admin of the team's Source, or someone who manages the team's agents, confirms what an agent may use."
168
- : 'Run "ekanos sources" to list the sources you hold a seat on.');
179
+ : code === 'PERSONAL_AGENT_CREATOR_ONLY'
180
+ ? 'A personal agent acts with its creator\'s own connections, so only they change it, run it, decide its approvals or cancel its runs. "ekanos teams agents list <team>" shows whose each agent is.'
181
+ : code === 'NOT_A_TEAM_MEMBER'
182
+ ? 'Add yourself to the team first ("ekanos teams members add <team> --self"), then run this again.'
183
+ : code === 'AGENTS_MANAGE_REQUIRED'
184
+ ? 'Take a role on the team that holds agents.manage ("ekanos teams roles list <team>"), or make it your own agent with --personal.'
185
+ : code === 'PERSONAL_AGENT_CHANNEL_TRIGGER'
186
+ ? 'Add a schedule or a webhook trigger instead: "ekanos teams triggers add <team> <key> schedule|webhook --prompt ...".'
187
+ : 'Run "ekanos sources" to list the sources you hold a seat on.');
169
188
  }
170
189
  if (response.status === 404) {
171
- throw notFoundError(message !== null && message !== void 0 ? message : 'Not found.', code === 'TEAM_NOT_FOUND'
190
+ throw notFoundError(message !== null && message !== void 0 ? message : 'Not found.', (_a = (code ? LIFECYCLE_HINTS[code] : undefined)) !== null && _a !== void 0 ? _a : (code === 'TEAM_NOT_FOUND'
172
191
  ? 'Run "ekanos teams list" to see the teams on this Source.'
173
192
  : code === 'PRODUCT_NOT_ENTITLED'
174
193
  ? '"ekanos sources products" shows what this Source has; only a super-admin enables a product for a Source (in /admin).'
@@ -178,37 +197,56 @@ export async function call(host, accessToken, schema, init) {
178
197
  ? 'Run "ekanos teams show <team> <product>" to see its team apps and webhooks.'
179
198
  : code === 'MEMBER_NOT_FOUND'
180
199
  ? 'Run "ekanos teams members list <team>" to see its members and invitations.'
181
- : code === 'SKILL_NOT_FOUND'
182
- ? 'Run "ekanos skills list --team <team>" (and "ekanos skills list") to see the skills this team can use.'
183
- : (code === null || code === void 0 ? void 0 : code.startsWith('AGENT_')) || code === 'TEMPLATE_NOT_FOUND'
184
- ? 'Run "ekanos teams agents list <team>" to see the team\'s agents.'
185
- : /^(TRIGGER|LINK|MCP)_/.test(code !== null && code !== void 0 ? code : '')
186
- ? 'List them first: "ekanos teams triggers|links|mcp list <team> ..."'
187
- : 'Run "ekanos sources" to list the sources you hold a seat on.');
200
+ : code === 'NOT_A_SOURCE_USER'
201
+ ? 'Invite them instead, by email: "ekanos teams members invite <team> <email> --role <role>".'
202
+ : code === 'SKILL_NOT_FOUND'
203
+ ? 'Run "ekanos skills list --team <team>" (and "ekanos skills list") to see the skills this team can use.'
204
+ : (code === null || code === void 0 ? void 0 : code.startsWith('AGENT_')) ||
205
+ code === 'TEMPLATE_NOT_FOUND'
206
+ ? 'Run "ekanos teams agents list <team>" to see the team\'s agents.'
207
+ : /^(TRIGGER|LINK|MCP)_/.test(code !== null && code !== void 0 ? code : '')
208
+ ? 'List them first: "ekanos teams triggers|links|mcp list <team> ..."'
209
+ : 'Run "ekanos sources" to list the sources you hold a seat on.'));
188
210
  }
189
211
  if (response.status === 409 && code === 'NO_TEAM_APP') {
190
212
  throw invalidStateError(message !== null && message !== void 0 ? message : 'This integration takes no team app.', 'Teams connect through the Source\'s app: "ekanos apps show <product>".');
191
213
  }
192
214
  if (response.status === 409 || response.status === 422) {
193
- throw invalidStateError(message !== null && message !== void 0 ? message : 'The host refused the change.', code === 'SLUG_TAKEN'
215
+ throw invalidStateError(message !== null && message !== void 0 ? message : 'The host refused the change.', (_b = (code ? LIFECYCLE_HINTS[code] : undefined)) !== null && _b !== void 0 ? _b : (code === 'SLUG_TAKEN'
194
216
  ? 'Pick another with --slug, or run "ekanos teams list" to see the teams.'
195
217
  : code === 'AGENT_VERSION_CHANGED'
196
218
  ? 'A newer version was published since it was shown to you. Review it with "ekanos teams agents show <team> <key>", then run "ekanos teams agents confirm" again.'
197
- : code === 'ALREADY_MEMBER' || code === 'ALREADY_INVITED'
198
- ? 'Run "ekanos teams members list <team>"; change a role with "ekanos teams members role <team> <email> <role>".'
199
- : code === 'PRIMARY_OWNER'
200
- ? "The primary owner's ownership is transferred in the app (team Settings → Members)."
201
- : code === 'TEAM_ACCOUNTS_DISABLED'
202
- ? 'Ekanos switches team accounts on for a Source; ask a super-admin.'
203
- : code === 'PERSONAL_CONNECTION'
204
- ? "The member who made it disconnects it on the team's Integrations page in the app."
205
- : code === 'MCP_SERVER_FROM_TEMPLATE'
206
- ? 'It stays while the agent template declares it: change the template, apply and publish.'
207
- : code === 'PRODUCT_NOT_ENTITLED'
208
- ? '"ekanos sources products" shows what this Source has; only those can be in its scopes.'
209
- : code === 'TEMPLATE_ARCHIVED'
210
- ? 'Unarchive it first: "ekanos agents unarchive <key>".'
211
- : 'See "ekanos teams --help".');
219
+ : code === 'ROLE_NEEDS_ACCEPTANCE'
220
+ ? 'Add them with a lower role (--role admin), or invite them to the top role so they accept it: "ekanos teams members invite <team> <email> --role owner".'
221
+ : code === 'AGENT_VERSION_CONFLICT'
222
+ ? `Review it with "ekanos teams agents show <team> <key>", then apply with --base-version ${typeof body.latestVersion === 'number' ? body.latestVersion : '<its version>'} (or --overwrite to replace it anyway).`
223
+ : code === 'ALREADY_MEMBER' || code === 'ALREADY_INVITED'
224
+ ? 'Run "ekanos teams members list <team>"; change a role with "ekanos teams members role <team> <email> <role>".'
225
+ : code === 'PRIMARY_OWNER'
226
+ ? "The primary owner's ownership is transferred in the app (team Settings → Members)."
227
+ : code === 'TEAM_ACCOUNTS_DISABLED'
228
+ ? 'Ekanos switches team accounts on for a Source; ask a super-admin.'
229
+ : code === 'PERSONAL_CONNECTION'
230
+ ? 'Each member disconnects their own: "ekanos teams disconnect <team> <product> --mine".'
231
+ : code === 'MCP_SERVER_FROM_TEMPLATE'
232
+ ? 'It stays while the agent template declares it: change the template, apply and publish.'
233
+ : code === 'PRODUCT_NOT_ENTITLED'
234
+ ? '"ekanos sources products" shows what this Source has; only those can be in its scopes.'
235
+ : code === 'TEMPLATE_ARCHIVED'
236
+ ? 'Unarchive it first: "ekanos agents unarchive <key>".'
237
+ : 'See "ekanos teams --help".'));
238
+ }
239
+ if (response.status === 400 && code === 'INVALID_AGENT') {
240
+ const issues = Array.isArray(body.issues)
241
+ ? body.issues.flatMap((issue) => { var _a; return typeof issue === 'object' &&
242
+ issue !== null &&
243
+ typeof issue.message === 'string'
244
+ ? [
245
+ ` ${String((_a = issue.path) !== null && _a !== void 0 ? _a : '(root)')}: ${issue.message}`,
246
+ ]
247
+ : []; })
248
+ : [];
249
+ throw validationError([message !== null && message !== void 0 ? message : 'The agent is not valid.', ...issues].join('\n'), 'Fix agent.json and run it again.');
212
250
  }
213
251
  if (response.status === 400 && code === 'UNKNOWN_ROLE') {
214
252
  throw validationError(message !== null && message !== void 0 ? message : 'No such role.', 'Run "ekanos teams roles list <team>" for the roles this Source uses.');
@@ -216,9 +254,15 @@ export async function call(host, accessToken, schema, init) {
216
254
  if (response.status === 400 && code === 'INVALID_FIELDS') {
217
255
  throw validationError(message !== null && message !== void 0 ? message : 'The host refused the fields.', 'Run "ekanos teams app set <team> <product>" again.');
218
256
  }
257
+ if (response.status === 400 && code === 'SECRET_AS_ARGUMENT') {
258
+ throw usageError(message !== null && message !== void 0 ? message : 'A secret was passed as an argument.', 'Leave that field out of --set: pass it with --set-secret <field>=env:<NAME>|file:<path>|stdin or --browser, or run the command at your terminal, which asks for it hidden.');
259
+ }
219
260
  if (response.status === 400) {
220
261
  throw usageError(message !== null && message !== void 0 ? message : 'The host refused the request.', 'See "ekanos teams --help".');
221
262
  }
263
+ if (response.status >= 500 && code && message) {
264
+ throw networkError(message, 'The host could not finish it; retry shortly.');
265
+ }
222
266
  if (!response.ok) {
223
267
  throw networkError(`${host}${init.path} responded ${response.status}.`, response.status >= 500
224
268
  ? 'The Ekanos deployment returned a server error. Retry shortly.'
@@ -230,6 +274,23 @@ export async function call(host, accessToken, schema, init) {
230
274
  }
231
275
  return { status: 'ok', data: parsed.data };
232
276
  }
277
+ /** Next steps for the refusals of the team lifecycle, roles and groups calls. */
278
+ const LIFECYCLE_HINTS = {
279
+ GROUP_NOT_FOUND: 'Run "ekanos teams groups list <team>" to see its groups (name one by name or id).',
280
+ GROUP_AMBIGUOUS: 'Run "ekanos teams groups list <team> --json" and name the group by its id.',
281
+ GROUP_EXISTS: 'Pick another name, or change that group: "ekanos teams groups update <team> <group> …".',
282
+ ROLE_NOT_FOUND: 'Run "ekanos sources roles list" to see the Source\'s roles.',
283
+ ROLE_EXISTS: 'Change it instead: "ekanos sources roles update <role> …", or pick another name.',
284
+ SYSTEM_ROLE: 'Owner, admin and member are fixed; create a custom role with "ekanos sources roles create <name> …".',
285
+ ROLE_IN_USE: 'Give its members another role first: "ekanos teams members role <team> <email> <role>"; "ekanos sources people" shows who holds what.',
286
+ WORKSPACE_NOT_FOUND: 'Run "ekanos teams workspace list <team>" to see its workspaces.',
287
+ WORKSPACES_DISABLED: 'Workspaces are a Source Flag (enable_workspaces) only a super-admin switches.',
288
+ NOT_A_MEMBER: 'Run "ekanos teams members list <team>" to see who is on it; you leave only a team you are a member of.',
289
+ NOT_CONNECTED: 'Connect it first: "ekanos teams connect <team> <product>"; "ekanos teams health <team>" lists what it has.',
290
+ USER_SCOPED: 'Each person connects it for themselves and checks it on their own Integrations → Health page.',
291
+ NO_HEALTH_CHECK: 'The product has no package on this deployment; "ekanos sources products" shows what is registered.',
292
+ PRODUCT_NOT_VISIBLE_TO_TEAM: 'Run "ekanos teams scope show <team>" for the products the team sees.',
293
+ };
233
294
  async function readOptionalJson(response) {
234
295
  try {
235
296
  const parsed = await response.json();