@cosmoops/connect-sdk 0.6.0 → 0.9.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 (138) hide show
  1. package/CHANGELOG.md +165 -0
  2. package/README.md +273 -91
  3. package/dist/cjs/cli/doctor.js +3 -3
  4. package/dist/cjs/cli/init.js +3 -3
  5. package/dist/cjs/client/components/access-gate.js +42 -7
  6. package/dist/cjs/client/components/account-sessions.js +3 -3
  7. package/dist/cjs/client/components/ai-format.js +135 -0
  8. package/dist/cjs/client/components/ai-widgets.js +232 -0
  9. package/dist/cjs/client/components/app-shell.js +9 -8
  10. package/dist/cjs/client/components/apps-grid.js +3 -3
  11. package/dist/cjs/client/components/ask-ai.js +334 -0
  12. package/dist/cjs/client/components/feature-gate.js +2 -2
  13. package/dist/cjs/client/components/integrations-modal.js +1 -1
  14. package/dist/cjs/client/components/logo.js +3 -3
  15. package/dist/cjs/client/components/nav.js +1 -1
  16. package/dist/cjs/client/components/plan-pricing.js +1 -1
  17. package/dist/cjs/client/components/plans.js +6 -6
  18. package/dist/cjs/client/components/readiness.js +3 -3
  19. package/dist/cjs/client/components/side-nav.js +1 -1
  20. package/dist/cjs/client/components/subscribe-dialog.js +2 -2
  21. package/dist/cjs/client/components/subscription.js +1 -1
  22. package/dist/cjs/client/components/usage-meter.js +1 -1
  23. package/dist/cjs/client/components/user-menu.js +31 -8
  24. package/dist/cjs/client/components/workspace-type-gate.js +48 -0
  25. package/dist/cjs/client/index.js +32 -4
  26. package/dist/cjs/client/mark.js +1 -1
  27. package/dist/cjs/client/provider.js +50 -7
  28. package/dist/cjs/client/use-checkout.js +3 -3
  29. package/dist/cjs/errors.js +4 -4
  30. package/dist/cjs/helpers.js +1 -1
  31. package/dist/cjs/index.js +1 -1
  32. package/dist/cjs/next/index.js +2 -2
  33. package/dist/cjs/server/client.js +15 -15
  34. package/dist/cjs/server/handler.js +56 -13
  35. package/dist/cjs/server/http.js +47 -25
  36. package/dist/cjs/server/resources/access.js +3 -3
  37. package/dist/cjs/server/resources/ai.js +1 -1
  38. package/dist/cjs/server/resources/analytics.js +2 -2
  39. package/dist/cjs/server/resources/apps.js +4 -4
  40. package/dist/cjs/server/resources/billing.js +5 -5
  41. package/dist/cjs/server/resources/drive.js +4 -4
  42. package/dist/cjs/server/resources/entitlements.js +48 -7
  43. package/dist/cjs/server/resources/identity.js +6 -4
  44. package/dist/cjs/server/resources/integrations.js +13 -13
  45. package/dist/cjs/server/resources/logs.js +3 -3
  46. package/dist/cjs/server/resources/sessions.js +6 -6
  47. package/dist/cjs/server/webhooks.js +4 -4
  48. package/dist/cjs/types.js +1 -1
  49. package/dist/esm/cli/doctor.js +3 -3
  50. package/dist/esm/cli/init.js +3 -3
  51. package/dist/esm/client/components/access-gate.js +43 -8
  52. package/dist/esm/client/components/account-sessions.js +3 -3
  53. package/dist/esm/client/components/ai-format.js +129 -0
  54. package/dist/esm/client/components/ai-widgets.js +223 -0
  55. package/dist/esm/client/components/app-shell.js +8 -7
  56. package/dist/esm/client/components/apps-grid.js +3 -3
  57. package/dist/esm/client/components/ask-ai.js +331 -0
  58. package/dist/esm/client/components/feature-gate.js +2 -2
  59. package/dist/esm/client/components/integrations-modal.js +1 -1
  60. package/dist/esm/client/components/logo.js +3 -3
  61. package/dist/esm/client/components/nav.js +1 -1
  62. package/dist/esm/client/components/plan-pricing.js +1 -1
  63. package/dist/esm/client/components/plans.js +6 -6
  64. package/dist/esm/client/components/readiness.js +3 -3
  65. package/dist/esm/client/components/side-nav.js +1 -1
  66. package/dist/esm/client/components/subscribe-dialog.js +2 -2
  67. package/dist/esm/client/components/subscription.js +1 -1
  68. package/dist/esm/client/components/usage-meter.js +1 -1
  69. package/dist/esm/client/components/user-menu.js +31 -8
  70. package/dist/esm/client/components/workspace-type-gate.js +45 -0
  71. package/dist/esm/client/index.js +14 -3
  72. package/dist/esm/client/mark.js +1 -1
  73. package/dist/esm/client/provider.js +48 -7
  74. package/dist/esm/client/use-checkout.js +3 -3
  75. package/dist/esm/errors.js +4 -4
  76. package/dist/esm/helpers.js +1 -1
  77. package/dist/esm/index.js +1 -1
  78. package/dist/esm/next/index.js +2 -2
  79. package/dist/esm/server/client.js +15 -15
  80. package/dist/esm/server/handler.js +56 -13
  81. package/dist/esm/server/http.js +47 -25
  82. package/dist/esm/server/resources/access.js +3 -3
  83. package/dist/esm/server/resources/ai.js +1 -1
  84. package/dist/esm/server/resources/analytics.js +2 -2
  85. package/dist/esm/server/resources/apps.js +4 -4
  86. package/dist/esm/server/resources/billing.js +5 -5
  87. package/dist/esm/server/resources/drive.js +4 -4
  88. package/dist/esm/server/resources/entitlements.js +48 -7
  89. package/dist/esm/server/resources/identity.js +6 -4
  90. package/dist/esm/server/resources/integrations.js +13 -13
  91. package/dist/esm/server/resources/logs.js +3 -3
  92. package/dist/esm/server/resources/sessions.js +6 -6
  93. package/dist/esm/server/webhooks.js +4 -4
  94. package/dist/esm/types.js +1 -1
  95. package/dist/theme.css +87 -0
  96. package/dist/types/client/components/access-gate.d.ts +18 -4
  97. package/dist/types/client/components/account-sessions.d.ts +1 -1
  98. package/dist/types/client/components/ai-format.d.ts +24 -0
  99. package/dist/types/client/components/ai-widgets.d.ts +42 -0
  100. package/dist/types/client/components/app-shell.d.ts +25 -9
  101. package/dist/types/client/components/apps-grid.d.ts +1 -1
  102. package/dist/types/client/components/ask-ai.d.ts +73 -0
  103. package/dist/types/client/components/feature-gate.d.ts +1 -1
  104. package/dist/types/client/components/integrations-modal.d.ts +1 -1
  105. package/dist/types/client/components/logo.d.ts +5 -5
  106. package/dist/types/client/components/nav.d.ts +3 -3
  107. package/dist/types/client/components/plan-pricing.d.ts +2 -2
  108. package/dist/types/client/components/readiness.d.ts +2 -2
  109. package/dist/types/client/components/side-nav.d.ts +1 -1
  110. package/dist/types/client/components/subscribe-dialog.d.ts +3 -3
  111. package/dist/types/client/components/usage-meter.d.ts +1 -1
  112. package/dist/types/client/components/user-menu.d.ts +4 -3
  113. package/dist/types/client/components/workspace-type-gate.d.ts +48 -0
  114. package/dist/types/client/index.d.ts +11 -4
  115. package/dist/types/client/mark.d.ts +1 -1
  116. package/dist/types/client/provider.d.ts +52 -9
  117. package/dist/types/client/use-checkout.d.ts +3 -3
  118. package/dist/types/errors.d.ts +4 -4
  119. package/dist/types/helpers.d.ts +1 -1
  120. package/dist/types/index.d.ts +1 -1
  121. package/dist/types/next/index.d.ts +1 -1
  122. package/dist/types/server/client.d.ts +13 -13
  123. package/dist/types/server/handler.d.ts +2 -2
  124. package/dist/types/server/http.d.ts +6 -1
  125. package/dist/types/server/resources/access.d.ts +3 -3
  126. package/dist/types/server/resources/ai.d.ts +2 -2
  127. package/dist/types/server/resources/analytics.d.ts +2 -2
  128. package/dist/types/server/resources/apps.d.ts +4 -4
  129. package/dist/types/server/resources/billing.d.ts +4 -4
  130. package/dist/types/server/resources/drive.d.ts +4 -4
  131. package/dist/types/server/resources/entitlements.d.ts +37 -5
  132. package/dist/types/server/resources/identity.d.ts +2 -2
  133. package/dist/types/server/resources/integrations.d.ts +9 -9
  134. package/dist/types/server/resources/logs.d.ts +3 -3
  135. package/dist/types/server/resources/sessions.d.ts +5 -5
  136. package/dist/types/server/webhooks.d.ts +4 -4
  137. package/dist/types/types.d.ts +235 -61
  138. package/package.json +8 -2
@@ -94,9 +94,9 @@ function redirect(location, cookies = []) {
94
94
  * export { handler as GET, handler as POST };
95
95
  * ```
96
96
  *
97
- * Every route resolves the organization from the caller's *own* session, never
97
+ * Every route resolves the workspace from the caller's *own* session, never
98
98
  * from a query parameter. A browser must not be able to ask about an
99
- * organization it is not signed into, and a client-supplied `organizationId`
99
+ * workspace it is not signed into, and a client-supplied `workspaceId`
100
100
  * is exactly that hole.
101
101
  */
102
102
  function createConnectHandler(options) {
@@ -163,7 +163,7 @@ function createConnectHandler(options) {
163
163
  }
164
164
  return token;
165
165
  }
166
- /** Signed-in identity plus the organization it belongs to - the first read every other route needs. */
166
+ /** Signed-in identity plus the workspace it belongs to - the first read every other route needs. */
167
167
  async function whoami(request) {
168
168
  return client.identity.getUser(await requireToken(request));
169
169
  }
@@ -173,32 +173,75 @@ function createConnectHandler(options) {
173
173
  // Signed out is a normal state for a page rendering a Login button, not
174
174
  // an error - `user: null` rather than a 401 the client must catch.
175
175
  if (!token)
176
- return json({ user: null, subscription: null, serviceRole: null });
176
+ return json({ user: null, subscription: null, applicationRole: null });
177
177
  return json(await client.identity.getUser(token));
178
178
  },
179
179
  "GET /entitlements": async (request) => {
180
180
  const { user } = await whoami(request);
181
181
  const [readiness, subscription] = await Promise.all([
182
- client.entitlements.getReadiness(user.organizationId),
183
- client.entitlements.getSubscription(user.organizationId),
182
+ client.entitlements.getReadiness(user.workspaceId),
183
+ client.entitlements.getSubscription(user.workspaceId),
184
184
  ]);
185
185
  return json({ readiness, subscription });
186
186
  },
187
187
  "GET /plans": async () => json(await client.billing.listPlans()),
188
- // Organization comes from the caller's own session, same as every other
188
+ // Workspace comes from the caller's own session, same as every other
189
189
  // route here - a browser must not be able to ask what another workspace
190
190
  // has left.
191
191
  "GET /addons": async (request) => {
192
192
  const { user } = await whoami(request);
193
- return json(await client.billing.getAddonUsage(user.organizationId));
193
+ return json(await client.billing.getAddonUsage(user.workspaceId));
194
194
  },
195
195
  "GET /apps": async (request) => {
196
196
  const { user } = await whoami(request);
197
- return json({ apps: await client.apps.list(user.organizationId) });
197
+ return json({ apps: await client.apps.list(user.workspaceId) });
198
+ },
199
+ /**
200
+ * Ask AI. The one streaming route here, and the only one that does not
201
+ * answer JSON - it forwards Connect's server-sent event stream through
202
+ * untouched so `<ConnectAskAi>` can render tokens as they arrive.
203
+ *
204
+ * Same rule as every other route: the workspace comes from the caller's
205
+ * own session. It matters more here than anywhere else, because the
206
+ * answers are *retrieved from that workspace's Context Index* - a
207
+ * client-supplied `workspaceId` would be a read of another tenant's
208
+ * documents, laundered through a chat reply.
209
+ *
210
+ * Messages are forwarded as-is (part-based `UIMessage`s), and only their
211
+ * shape is checked: the conversation is the caller's own, and Connect
212
+ * validates it again on arrival.
213
+ */
214
+ "POST /ai/chat": async (request) => {
215
+ const { user } = await whoami(request);
216
+ const body = (await request.json().catch(() => null));
217
+ if (!Array.isArray(body?.messages)) {
218
+ throw new errors_js_1.ConnectError({
219
+ status: 400,
220
+ code: "validation_error",
221
+ message: "messages is required",
222
+ endpoint: "POST /ai/chat",
223
+ });
224
+ }
225
+ const upstream = await client.ai.chat({
226
+ workspaceId: user.workspaceId,
227
+ messages: body.messages,
228
+ });
229
+ // `upstream.body` is piped, never buffered - awaiting it would collect
230
+ // the whole answer server-side and deliver it in one lump, which is the
231
+ // only thing streaming was for. The browser cancelling its read
232
+ // propagates down this pipe and stops generation upstream.
233
+ return new Response(upstream.body, {
234
+ status: upstream.status,
235
+ headers: {
236
+ "content-type": upstream.headers.get("content-type") ?? "text/event-stream",
237
+ "cache-control": "no-store",
238
+ "x-content-type-options": "nosniff",
239
+ },
240
+ });
198
241
  },
199
242
  "GET /integrations": async (request) => {
200
243
  const { user } = await whoami(request);
201
- return json({ toolkits: await client.integrations.list(user.organizationId) });
244
+ return json({ toolkits: await client.integrations.list(user.workspaceId) });
202
245
  },
203
246
  "POST /integrations/connect": async (request) => {
204
247
  const { user } = await whoami(request);
@@ -211,7 +254,7 @@ function createConnectHandler(options) {
211
254
  endpoint: "POST /integrations/connect",
212
255
  });
213
256
  }
214
- return json(await client.integrations.initiateConnect(user.organizationId, body.toolkitSlug, body.returnUrl));
257
+ return json(await client.integrations.initiateConnect(user.workspaceId, body.toolkitSlug, body.returnUrl));
215
258
  },
216
259
  "POST /integrations/disconnect": async (request) => {
217
260
  const { user } = await whoami(request);
@@ -224,10 +267,10 @@ function createConnectHandler(options) {
224
267
  endpoint: "POST /integrations/disconnect",
225
268
  });
226
269
  }
227
- await client.integrations.disconnect(user.organizationId, body.toolkitSlug);
270
+ await client.integrations.disconnect(user.workspaceId, body.toolkitSlug);
228
271
  return json({ ok: true });
229
272
  },
230
- // Account-wide, not scoped to this service - see `SessionsResource`'s
273
+ // Account-wide, not scoped to this application - see `SessionsResource`'s
231
274
  // doc comment. `requireToken` alone identifies the caller; the target
232
275
  // `sessionId` on the revoke routes travels in the JSON body, not the
233
276
  // URL, so the exact-match routes table above never needs a dynamic
@@ -44,7 +44,7 @@ function parseRetryAfterMs(response) {
44
44
  return Number.isFinite(seconds) ? Math.max(0, seconds) * 1000 : null;
45
45
  }
46
46
  /**
47
- * Both error dialects, one shape. `/api/v1/service/*` answers
47
+ * Both error dialects, one shape. `/api/v1/application/*` answers
48
48
  * `{ error: { code, message } }`; the `/sso/*` endpoints answer OAuth2's
49
49
  * `{ error, error_description }`.
50
50
  */
@@ -128,33 +128,55 @@ async function request(options, spec) {
128
128
  // request for minutes.
129
129
  await sleep(Math.min(lastError?.retryAfterMs ?? 250 * 2 ** (attempt - 1), 8_000));
130
130
  }
131
- const timeout = AbortSignal.timeout(options.timeoutMs);
132
- const signal = spec.signal ? AbortSignal.any([spec.signal, timeout]) : timeout;
133
- let response;
131
+ // A cancellable timer rather than `AbortSignal.timeout`, because the
132
+ // timeout has to be *stopped* once this attempt is done reading - and a
133
+ // timeout signal cannot be cleared.
134
+ //
135
+ // That distinction is the whole point for a streaming endpoint. `fetch`
136
+ // resolves the moment the headers land, but its signal keeps governing
137
+ // the body: an `AbortSignal.timeout(20_000)` handed to `ai.chat` tears the
138
+ // SSE stream down mid-answer, twenty seconds in, on every conversation
139
+ // long enough to matter. Clearing the timer in `finally` bounds the
140
+ // request the same way it always did (a `raw` caller still gets its
141
+ // timeout on *reaching* Connect, and a JSON caller still gets it across
142
+ // the body read, which happens inside the `try`) while leaving a stream
143
+ // that has actually started to run as long as it needs. A caller that
144
+ // wants to bound the stream itself passes `spec.signal`.
145
+ const timeoutController = new AbortController();
146
+ const timer = setTimeout(() => timeoutController.abort(), options.timeoutMs);
147
+ const signal = spec.signal
148
+ ? AbortSignal.any([spec.signal, timeoutController.signal])
149
+ : timeoutController.signal;
134
150
  try {
135
- response = await options.fetch(url.toString(), { method: spec.method, headers, body, signal });
151
+ let response;
152
+ try {
153
+ response = await options.fetch(url.toString(), { method: spec.method, headers, body, signal });
154
+ }
155
+ catch (cause) {
156
+ // A caller-supplied abort is a decision, not a fault - never retried.
157
+ if (spec.signal?.aborted)
158
+ throw cause;
159
+ lastError = new errors_js_1.ConnectError({
160
+ status: 0,
161
+ code: "network_error",
162
+ message: `${endpoint} could not reach Connect`,
163
+ endpoint,
164
+ cause,
165
+ });
166
+ continue;
167
+ }
168
+ if (response.ok) {
169
+ if (spec.raw)
170
+ return response;
171
+ return (await readBody(response));
172
+ }
173
+ lastError = toConnectError(response, await readBody(response), endpoint);
174
+ if (!RETRYABLE_STATUS.has(response.status))
175
+ throw lastError;
136
176
  }
137
- catch (cause) {
138
- // A caller-supplied abort is a decision, not a fault - never retried.
139
- if (spec.signal?.aborted)
140
- throw cause;
141
- lastError = new errors_js_1.ConnectError({
142
- status: 0,
143
- code: "network_error",
144
- message: `${endpoint} could not reach Connect`,
145
- endpoint,
146
- cause,
147
- });
148
- continue;
177
+ finally {
178
+ clearTimeout(timer);
149
179
  }
150
- if (response.ok) {
151
- if (spec.raw)
152
- return response;
153
- return (await readBody(response));
154
- }
155
- lastError = toConnectError(response, await readBody(response), endpoint);
156
- if (!RETRYABLE_STATUS.has(response.status))
157
- throw lastError;
158
180
  }
159
181
  throw lastError;
160
182
  }
@@ -2,7 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.AccessResource = void 0;
4
4
  const http_js_1 = require("../http.js");
5
- /** What a signed-in member may do on your service, and the role catalog behind it. */
5
+ /** What a signed-in member may do on your application, and the role catalog behind it. */
6
6
  class AccessResource {
7
7
  transport;
8
8
  constructor(transport) {
@@ -17,10 +17,10 @@ class AccessResource {
17
17
  return (0, http_js_1.request)(this.transport, {
18
18
  method: "GET",
19
19
  path: `/rbac/users/${(0, http_js_1.pathSegment)(userId, "userId")}/roles`,
20
- query: { organizationId: input.organizationId },
20
+ query: { workspaceId: input.workspaceId },
21
21
  });
22
22
  }
23
- /** Your service's own permission catalog and role definitions - the definitions `getUserRoles` resolves against. */
23
+ /** Your application's own permission catalog and role definitions - the definitions `getUserRoles` resolves against. */
24
24
  listRoles() {
25
25
  return (0, http_js_1.request)(this.transport, { method: "GET", path: "/roles" });
26
26
  }
@@ -2,7 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.AiResource = void 0;
4
4
  const http_js_1 = require("../http.js");
5
- /** RAG chat and structured extraction against an organization's data. */
5
+ /** RAG chat and structured extraction against a workspace's data. */
6
6
  class AiResource {
7
7
  transport;
8
8
  constructor(transport) {
@@ -3,10 +3,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.AnalyticsResource = void 0;
4
4
  const http_js_1 = require("../http.js");
5
5
  /**
6
- * Your service's own analytics: emit product events, and read back the daily
6
+ * Your application's own analytics: emit product events, and read back the daily
7
7
  * numbers Connect aggregates from them.
8
8
  *
9
- * There is no way to name a service in either call. The scope is always the one
9
+ * There is no way to name an application in either call. The scope is always the one
10
10
  * your API key belongs to - that is the endpoint's security model, not an
11
11
  * omission.
12
12
  */
@@ -2,7 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.AppsResource = void 0;
4
4
  const http_js_1 = require("../http.js");
5
- /** The services an organization can open - the data behind a launcher grid. */
5
+ /** The applications a workspace can open - the data behind a launcher grid. */
6
6
  class AppsResource {
7
7
  transport;
8
8
  constructor(transport) {
@@ -10,13 +10,13 @@ class AppsResource {
10
10
  }
11
11
  /**
12
12
  * Launchable apps only, so a grid tile is never a dead end. The calling
13
- * service is included and flagged `isCurrent` rather than filtered out.
13
+ * application is included and flagged `isCurrent` rather than filtered out.
14
14
  */
15
- async list(organizationId) {
15
+ async list(workspaceId) {
16
16
  const result = await (0, http_js_1.request)(this.transport, {
17
17
  method: "GET",
18
18
  path: "/apps",
19
- query: { organizationId },
19
+ query: { workspaceId },
20
20
  });
21
21
  // `?? []` for the same reason `billing.listPlans` has it: this is a
22
22
  // collection every caller immediately maps or measures, and a body without
@@ -10,7 +10,7 @@ class BillingResource {
10
10
  this.transport = transport;
11
11
  }
12
12
  /**
13
- * Your service's active plans - render live pricing instead of hardcoding it.
13
+ * Your application's active plans - render live pricing instead of hardcoding it.
14
14
  *
15
15
  * `features` is normalised on the way out: Connect used to send bare keys
16
16
  * and now sends `{ key, name, description }`, and this SDK is versioned
@@ -28,7 +28,7 @@ class BillingResource {
28
28
  };
29
29
  }
30
30
  /**
31
- * What is left of every consumable add-on on an organization's
31
+ * What is left of every consumable add-on on a workspace's
32
32
  * subscription - the read half of `consumeAddon`.
33
33
  *
34
34
  * Needs a key scoped to `addons:read`, which is separate from
@@ -38,10 +38,10 @@ class BillingResource {
38
38
  * Returns an empty `addons` array rather than throwing when there is
39
39
  * nothing to meter, so a caller can render it unconditionally.
40
40
  */
41
- async getAddonUsage(organizationId) {
41
+ async getAddonUsage(workspaceId) {
42
42
  const response = await (0, http_js_1.request)(this.transport, {
43
43
  method: "GET",
44
- path: `/addons/organizations/${(0, http_js_1.pathSegment)(organizationId, "organizationId")}`,
44
+ path: `/addons/workspaces/${(0, http_js_1.pathSegment)(workspaceId, "workspaceId")}`,
45
45
  });
46
46
  // Normalised, not passed through: the promise above resolves for any 2xx,
47
47
  // and `ConnectUsageMeter` reads `addons` straight off it. A body without
@@ -52,7 +52,7 @@ class BillingResource {
52
52
  }
53
53
  /**
54
54
  * Debit a consumable add-on's per-cycle balance on behalf of an
55
- * organization's users. Call it at whatever cadence your usage happens.
55
+ * workspace's users. Call it at whatever cadence your usage happens.
56
56
  *
57
57
  * An `Idempotency-Key` is always sent, generated per call when you do not
58
58
  * supply one: a balance cannot be un-spent, so a retried consume without a
@@ -2,7 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.DriveResource = void 0;
4
4
  const http_js_1 = require("../http.js");
5
- /** Files in an organization's Drive - upload, and signed URLs to read back. */
5
+ /** Files in a workspace's Drive - upload, and signed URLs to read back. */
6
6
  class DriveResource {
7
7
  transport;
8
8
  constructor(transport) {
@@ -12,7 +12,7 @@ class DriveResource {
12
12
  const form = new FormData();
13
13
  const fileName = input.fileName ?? input.file.name ?? "upload";
14
14
  form.set("file", input.file, fileName);
15
- form.set("organizationId", input.organizationId);
15
+ form.set("workspaceId", input.workspaceId);
16
16
  if (input.parentId)
17
17
  form.set("parentId", input.parentId);
18
18
  return (0, http_js_1.request)(this.transport, { method: "POST", path: "/drive/files", multipart: form });
@@ -22,7 +22,7 @@ class DriveResource {
22
22
  const result = await (0, http_js_1.request)(this.transport, {
23
23
  method: "GET",
24
24
  path: `/drive/files/${(0, http_js_1.pathSegment)(fileId, "fileId")}/url`,
25
- query: { organizationId: input.organizationId },
25
+ query: { workspaceId: input.workspaceId },
26
26
  });
27
27
  return result.url;
28
28
  }
@@ -31,7 +31,7 @@ class DriveResource {
31
31
  const result = await (0, http_js_1.request)(this.transport, {
32
32
  method: "GET",
33
33
  path: `/drive/files/${(0, http_js_1.pathSegment)(fileId, "fileId")}/preview-url`,
34
- query: { organizationId: input.organizationId, size: input.size },
34
+ query: { workspaceId: input.workspaceId, size: input.size },
35
35
  });
36
36
  return result.url;
37
37
  }
@@ -12,7 +12,7 @@ class EntitlementsResource {
12
12
  this.transport = transport;
13
13
  }
14
14
  /**
15
- * Every gate Connect owns between an organization and your service -
15
+ * Every gate Connect owns between a workspace and your application -
16
16
  * subscription, KYC/KYB, a chargeable payment method, seat headroom -
17
17
  * resolved in one call.
18
18
  *
@@ -20,17 +20,17 @@ class EntitlementsResource {
20
20
  * Connect screen that fixes it, so you can route them somewhere useful
21
21
  * instead of refusing them with nowhere to go.
22
22
  */
23
- getReadiness(organizationId) {
23
+ getReadiness(workspaceId) {
24
24
  return (0, http_js_1.request)(this.transport, {
25
25
  method: "GET",
26
- path: `/onboarding/organizations/${(0, http_js_1.pathSegment)(organizationId, "organizationId")}`,
26
+ path: `/onboarding/workspaces/${(0, http_js_1.pathSegment)(workspaceId, "workspaceId")}`,
27
27
  });
28
28
  }
29
29
  /** The live plan and subscription, including `plan.features`. */
30
- getSubscription(organizationId) {
30
+ getSubscription(workspaceId) {
31
31
  return (0, http_js_1.request)(this.transport, {
32
32
  method: "GET",
33
- path: `/subscriptions/organizations/${(0, http_js_1.pathSegment)(organizationId, "organizationId")}`,
33
+ path: `/subscriptions/workspaces/${(0, http_js_1.pathSegment)(workspaceId, "workspaceId")}`,
34
34
  });
35
35
  }
36
36
  /**
@@ -41,9 +41,50 @@ class EntitlementsResource {
41
41
  * all: "not entitled" is the same answer either way, and a feature gate
42
42
  * should not need a try/catch around it.
43
43
  */
44
- async hasFeature(organizationId, feature) {
45
- const result = await this.getSubscription(organizationId);
44
+ async hasFeature(workspaceId, feature) {
45
+ const result = await this.getSubscription(workspaceId);
46
46
  return result.hasActiveSubscription && (result.plan?.features.includes(feature) ?? false);
47
47
  }
48
+ /**
49
+ * One page of the workspaces subscribed to your application, newest first.
50
+ *
51
+ * The inverse of `getSubscription`, which asks about one workspace you
52
+ * already know. This asks who your subscribers *are* - what a partner
53
+ * dashboard, an MRR total or a churn report is built on.
54
+ *
55
+ * Rate-limited far more tightly than the per-workspace read (10/min per
56
+ * key, against 60): it walks your whole subscriber base and is a reporting
57
+ * call, not a per-request gate. Use `getSubscription` in a hot path.
58
+ *
59
+ * Your application is resolved from the API key, so there is no parameter
60
+ * for it and no way to ask about anyone else's.
61
+ */
62
+ listSubscribers(options = {}) {
63
+ return (0, http_js_1.request)(this.transport, {
64
+ method: "GET",
65
+ path: "/subscriptions",
66
+ query: { status: options.status, before: options.before, limit: options.limit },
67
+ });
68
+ }
69
+ /**
70
+ * Every subscriber, paged through for you.
71
+ *
72
+ * An async generator rather than an array: a large subscriber base is
73
+ * exactly where an accidental full materialisation hurts, and `for await`
74
+ * reads the same as a loop over one page.
75
+ */
76
+ async *iterateSubscribers(options = {}) {
77
+ let before;
78
+ do {
79
+ const page = await this.listSubscribers({
80
+ status: options.status,
81
+ limit: options.pageSize,
82
+ before,
83
+ });
84
+ for (const item of page.items)
85
+ yield item;
86
+ before = page.nextBefore ?? undefined;
87
+ } while (before);
88
+ }
48
89
  }
49
90
  exports.EntitlementsResource = EntitlementsResource;
@@ -70,7 +70,8 @@ class IdentityResource {
70
70
  sessionTokenExpiresIn: wire.session_token_expires_in,
71
71
  user: wire.user,
72
72
  subscription: wire.subscription,
73
- serviceRole: wire.serviceRole,
73
+ applicationRole: wire.applicationRole,
74
+ audience: wire.audience,
74
75
  };
75
76
  }
76
77
  /**
@@ -140,7 +141,8 @@ class IdentityResource {
140
141
  return {
141
142
  user: wire.user,
142
143
  subscription: wire.subscription,
143
- serviceRole: wire.serviceRole,
144
+ applicationRole: wire.applicationRole,
145
+ audience: wire.audience,
144
146
  sessionExpiresAt: wire.session_expires_at,
145
147
  };
146
148
  }
@@ -149,7 +151,7 @@ class IdentityResource {
149
151
  * rest of its ~15-day life. Discard your own copy of `sessionToken` too;
150
152
  * this does not do that for you.
151
153
  *
152
- * `scope` defaults to `"device"`: this sign-in, every other service signed
154
+ * `scope` defaults to `"device"`: this sign-in, every other application signed
153
155
  * into from the same browser, and Connect's own session on that one device.
154
156
  * `"all"` ends every session on every device - an explicit "sign out
155
157
  * everywhere" action only.
@@ -181,7 +183,7 @@ class IdentityResource {
181
183
  throw new errors_js_1.ConnectError({
182
184
  status: 0,
183
185
  code: "missing_client_id",
184
- message: "identity.* needs `clientId`. Pass it to `new ConnectClient({ clientId, apiKey })` - it is shown in this service's Integration tab, under Connect client.",
186
+ message: "identity.* needs `clientId`. Pass it to `new ConnectClient({ clientId, apiKey })` - it is shown in this application's Integration tab, under Connect client.",
185
187
  endpoint: "identity",
186
188
  });
187
189
  }
@@ -4,8 +4,8 @@ exports.IntegrationsResource = void 0;
4
4
  const http_js_1 = require("../http.js");
5
5
  /**
6
6
  * Composio-hosted third-party connections (Google Calendar, Slack,
7
- * Twitter/X, ...) an organization has connected. Connect proxies every call
8
- * here - your service never sees or holds the underlying OAuth token, which
7
+ * Twitter/X, ...) a workspace has connected. Connect proxies every call
8
+ * here - your application never sees or holds the underlying OAuth token, which
9
9
  * stays with Composio.
10
10
  */
11
11
  class IntegrationsResource {
@@ -13,12 +13,12 @@ class IntegrationsResource {
13
13
  constructor(transport) {
14
14
  this.transport = transport;
15
15
  }
16
- /** Enabled toolkits and this organization's connection status for each. */
17
- async list(organizationId) {
16
+ /** Enabled toolkits and this workspace's connection status for each. */
17
+ async list(workspaceId) {
18
18
  const result = await (0, http_js_1.request)(this.transport, {
19
19
  method: "GET",
20
20
  path: "/integrations",
21
- query: { organizationId },
21
+ query: { workspaceId },
22
22
  });
23
23
  // `?? []` for the same reason `AppsResource.list` has it - a collection
24
24
  // every caller immediately maps or measures.
@@ -35,31 +35,31 @@ class IntegrationsResource {
35
35
  * itself. Reconnecting a disconnected/failed toolkit calls this same
36
36
  * method - there is no separate reconnect.
37
37
  *
38
- * Meant to be called on behalf of a signed-in org admin (this is what the
38
+ * Meant to be called on behalf of a signed-in workspace admin (this is what the
39
39
  * bridge's fixed `POST /integrations/connect` route does), not as a bare
40
40
  * background action with no admin present to complete the OAuth screen.
41
41
  */
42
- async initiateConnect(organizationId, toolkitSlug, returnUrl) {
42
+ async initiateConnect(workspaceId, toolkitSlug, returnUrl) {
43
43
  return (0, http_js_1.request)(this.transport, {
44
44
  method: "POST",
45
45
  path: "/integrations/connect",
46
- json: { organizationId, toolkitSlug, returnUrl },
46
+ json: { workspaceId, toolkitSlug, returnUrl },
47
47
  });
48
48
  }
49
49
  /** Idempotent - disconnecting a toolkit that was never connected, or is already disconnected, is a success. */
50
- async disconnect(organizationId, toolkitSlug) {
50
+ async disconnect(workspaceId, toolkitSlug) {
51
51
  return (0, http_js_1.request)(this.transport, {
52
52
  method: "POST",
53
53
  path: "/integrations/disconnect",
54
- json: { organizationId, toolkitSlug },
54
+ json: { workspaceId, toolkitSlug },
55
55
  });
56
56
  }
57
- /** Calls a Composio action against this organization's connected account for the named toolkit. */
58
- async execute(organizationId, input) {
57
+ /** Calls a Composio action against this workspace's connected account for the named toolkit. */
58
+ async execute(workspaceId, input) {
59
59
  return (0, http_js_1.request)(this.transport, {
60
60
  method: "POST",
61
61
  path: "/integrations/actions/execute",
62
- json: { organizationId, ...input },
62
+ json: { workspaceId, ...input },
63
63
  });
64
64
  }
65
65
  }
@@ -2,7 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.LogsResource = void 0;
4
4
  const http_js_1 = require("../http.js");
5
- /** Push feature events into the Console's audit log, filterable to your service. */
5
+ /** Push feature events into the Console's audit log, filterable to your application. */
6
6
  class LogsResource {
7
7
  transport;
8
8
  constructor(transport) {
@@ -14,9 +14,9 @@ class LogsResource {
14
14
  * reported through the return value.
15
15
  *
16
16
  * Pass `sessionToken` to attribute the event to the end user it belongs to.
17
- * Both scopes on the stored entry come from something verified - the service
17
+ * Both scopes on the stored entry come from something verified - the application
18
18
  * from your API key, the user from that token, which Connect checks was
19
- * minted for your service before attributing anything. `attributed` in the
19
+ * minted for your application before attributing anything. `attributed` in the
20
20
  * result says whether it resolved; a `false` there still means the line was
21
21
  * stored, just without a user on it.
22
22
  */
@@ -8,11 +8,11 @@ const http_js_1 = require("../http.js");
8
8
  * timestamps - the same list Connect's own account settings page shows the
9
9
  * user themselves.
10
10
  *
11
- * **Account-wide, not scoped to this service.** A Connect session is one
12
- * browser's login to Connect, and it fans out to every partner service's own
13
- * `sessionToken` - Connect has no per-service session concept to filter by.
11
+ * **Account-wide, not scoped to this application.** A Connect session is one
12
+ * browser's login to Connect, and it fans out to every partner application's own
13
+ * `sessionToken` - Connect has no per-application session concept to filter by.
14
14
  * `list()` returns every session on the account, including ones that
15
- * originated from a completely different, unrelated service. Requires the
15
+ * originated from a completely different, unrelated application. Requires the
16
16
  * `sessions:manage` scope on your API key - unlike `identity`'s base `sso`
17
17
  * capability, this is never granted to a zero-scope legacy key by default.
18
18
  *
@@ -38,7 +38,7 @@ class SessionsResource {
38
38
  }
39
39
  /**
40
40
  * Ends one specific session by id - not necessarily the one `sessionToken`
41
- * itself was minted from. Cascades to every partner-service sign-in that
41
+ * itself was minted from. Cascades to every partner-application sign-in that
42
42
  * originated from that same browser, same as Connect's own "sign out this
43
43
  * device".
44
44
  */
@@ -72,7 +72,7 @@ class SessionsResource {
72
72
  throw new errors_js_1.ConnectError({
73
73
  status: 0,
74
74
  code: "missing_client_id",
75
- message: "sessions.* needs `clientId`. Pass it to `new ConnectClient({ clientId, apiKey })` - it is shown in this service's Integration tab, under Connect client.",
75
+ message: "sessions.* needs `clientId`. Pass it to `new ConnectClient({ clientId, apiKey })` - it is shown in this application's Integration tab, under Connect client.",
76
76
  endpoint: "sessions",
77
77
  });
78
78
  }
@@ -58,10 +58,10 @@ function verifyConnectWebhook(rawBody, signatureHeader, secret, now = new Date()
58
58
  * export const POST = createConnectWebhookHandler({
59
59
  * secret: process.env.CONNECT_WEBHOOK_SECRET!,
60
60
  * on: {
61
- * "organization.deletion_scheduled": ({ organizationId, purgeAfter }) =>
62
- * freeze(organizationId, purgeAfter),
63
- * "organization.deletion_cancelled": ({ organizationId }) => unfreeze(organizationId),
64
- * "organization.deleted": ({ organizationId }) => purge(organizationId),
61
+ * "workspace.deletion_scheduled": ({ workspaceId, purgeAfter }) =>
62
+ * freeze(workspaceId, purgeAfter),
63
+ * "workspace.deletion_cancelled": ({ workspaceId }) => unfreeze(workspaceId),
64
+ * "workspace.deleted": ({ workspaceId }) => purge(workspaceId),
65
65
  * },
66
66
  * })
67
67
  * ```
package/dist/cjs/types.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  /**
3
- * Wire types for the `/api/v1/service/*` surface - the service-partner API,
3
+ * Wire types for the `/api/v1/application/*` surface - the application-partner API,
4
4
  * and the only thing this SDK covers.
5
5
  *
6
6
  * Hand-written rather than generated so the published package carries no