@agentforge-io/sdk-server 4.2.0 → 4.4.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.
- package/dist/resources/connectors.d.ts +108 -2
- package/dist/resources/connectors.js +147 -2
- package/dist/types.d.ts +17 -0
- package/package.json +1 -1
|
@@ -227,8 +227,9 @@ export declare class ConnectorsResource {
|
|
|
227
227
|
* `listConnected()`, which is the ak_live_ tenant-wide picker). Returns
|
|
228
228
|
* the SAME rich shape `listForTenant`/`listForUser` produce server-side
|
|
229
229
|
* (`AppUserConnectorStatus`: name/description/category/iconUrl/configured/
|
|
230
|
-
* accountLabel/connectedAt)
|
|
231
|
-
*
|
|
230
|
+
* accountLabel/connectedAt), PLUS `browsable` (AGF-074, computed
|
|
231
|
+
* server-side on top of the raw `ConnectorStatus` rows) — NOT the narrow
|
|
232
|
+
* `ConnectorStatus` the tenant-picker methods above use.
|
|
232
233
|
*
|
|
233
234
|
* Requires `appSecret` — throws early otherwise, same as
|
|
234
235
|
* `authorizeForAppUser`.
|
|
@@ -263,6 +264,111 @@ export declare class ConnectorsResource {
|
|
|
263
264
|
}): Promise<{
|
|
264
265
|
ok: true;
|
|
265
266
|
}>;
|
|
267
|
+
/**
|
|
268
|
+
* `GET /app-user/connector-resources/:connectorId?externalUserId=...` —
|
|
269
|
+
* real resource browsing (Slack channels, GitHub repos, ClickUp lists…)
|
|
270
|
+
* scoped to ONE end user's OWN grant. App-user counterpart of
|
|
271
|
+
* `listResources()` above — same return shape, same `unsupported: true`
|
|
272
|
+
* behavior for connectors without a resource selector implemented yet.
|
|
273
|
+
*
|
|
274
|
+
* Requires `appSecret` — throws early otherwise, same as
|
|
275
|
+
* `authorizeForAppUser`.
|
|
276
|
+
*
|
|
277
|
+
* @example
|
|
278
|
+
* const { items } = await af.connectors.listResourcesForAppUser('slack', {
|
|
279
|
+
* externalUserId: 'scrappydoc-user-42',
|
|
280
|
+
* });
|
|
281
|
+
*/
|
|
282
|
+
listResourcesForAppUser(connectorId: string, input: {
|
|
283
|
+
externalUserId: string;
|
|
284
|
+
}): Promise<ListConnectorResourcesResult>;
|
|
285
|
+
/**
|
|
286
|
+
* `GET /app-user/connector-resources/:connectorId/defaults?externalUserId=...`
|
|
287
|
+
* — tool permissions for this connector, resolved with the App's own
|
|
288
|
+
* override always live (tier 0, `af_app_connectors`) since `appId` comes
|
|
289
|
+
* from the secret. App-user counterpart of `getDefaults()` above.
|
|
290
|
+
* `externalUserId` doesn't affect resolution (defaults are per-App, not
|
|
291
|
+
* per-end-user) — still required because the platform route always reads
|
|
292
|
+
* it off the scope helper shared by this controller's other routes.
|
|
293
|
+
*
|
|
294
|
+
* Requires `appSecret` — throws early otherwise, same as
|
|
295
|
+
* `authorizeForAppUser`.
|
|
296
|
+
*/
|
|
297
|
+
getDefaultsForAppUser(connectorId: string, input: {
|
|
298
|
+
externalUserId: string;
|
|
299
|
+
}): Promise<ConnectorDefaultsResult>;
|
|
300
|
+
/**
|
|
301
|
+
* `PUT /app-user/connector-resources/:connectorId/defaults?externalUserId=...`
|
|
302
|
+
* — overwrites the connector's tool permissions. App-user counterpart of
|
|
303
|
+
* `updateDefaults()` above. NOTE (mirrors the platform controller's own
|
|
304
|
+
* doc comment): this write lands on the tenant-level row
|
|
305
|
+
* (`af_connector_tool_defaults`), same as the ak_live_ route — there's no
|
|
306
|
+
* App-scoped-only override write today. `externalUserId` travels as a
|
|
307
|
+
* query param (matching `getDefaultsForAppUser`); the platform route also
|
|
308
|
+
* accepts it in the body but query is canonical for this SDK's GET/PUT
|
|
309
|
+
* pair.
|
|
310
|
+
*
|
|
311
|
+
* Requires `appSecret` — throws early otherwise, same as
|
|
312
|
+
* `authorizeForAppUser`.
|
|
313
|
+
*/
|
|
314
|
+
updateDefaultsForAppUser(connectorId: string, permissions: ToolPermission[], input: {
|
|
315
|
+
externalUserId: string;
|
|
316
|
+
}): Promise<{
|
|
317
|
+
ok: true;
|
|
318
|
+
}>;
|
|
319
|
+
/**
|
|
320
|
+
* `POST /app-user/connector-resources/clickup/tasks` — creates a REAL
|
|
321
|
+
* ClickUp task using the end user's OWN grant. App-user counterpart of
|
|
322
|
+
* `createClickupTask()` above. Unlike the GET/PUT methods above,
|
|
323
|
+
* `externalUserId` travels in the BODY here — the platform route reads it
|
|
324
|
+
* off `body.externalUserId` for this action endpoint (not a query param).
|
|
325
|
+
*
|
|
326
|
+
* Requires `appSecret` — throws early otherwise, same as
|
|
327
|
+
* `authorizeForAppUser`.
|
|
328
|
+
*/
|
|
329
|
+
createClickupTaskForAppUser(input: CreateClickupTaskInput & {
|
|
330
|
+
externalUserId: string;
|
|
331
|
+
}): Promise<CreateClickupTaskResult>;
|
|
332
|
+
/**
|
|
333
|
+
* `POST /app-user/connector-resources/slack/messages` — posts a REAL
|
|
334
|
+
* Slack message using the end user's OWN grant. App-user counterpart of
|
|
335
|
+
* `postSlackMessage()` above. `externalUserId` travels in the BODY, same
|
|
336
|
+
* as `createClickupTaskForAppUser` (the platform route reads
|
|
337
|
+
* `body.externalUserId` for both action endpoints).
|
|
338
|
+
*
|
|
339
|
+
* Requires `appSecret` — throws early otherwise, same as
|
|
340
|
+
* `authorizeForAppUser`.
|
|
341
|
+
*/
|
|
342
|
+
postSlackMessageForAppUser(input: {
|
|
343
|
+
channelId: string;
|
|
344
|
+
text: string;
|
|
345
|
+
externalUserId: string;
|
|
346
|
+
}): Promise<{
|
|
347
|
+
ok: true;
|
|
348
|
+
ts?: string;
|
|
349
|
+
permalink?: string;
|
|
350
|
+
}>;
|
|
351
|
+
/**
|
|
352
|
+
* `POST /app-user/connector-resources/:connectorId/api-key` — guarda un
|
|
353
|
+
* API key pegado por el end user, para SU PROPIO grant (no el tenant del
|
|
354
|
+
* App). App-user counterpart of `saveApiKeyForTenant()` above, para
|
|
355
|
+
* connectors que NO usan OAuth (Granola, Mapbox). `externalUserId` viaja
|
|
356
|
+
* en el BODY, mismo patrón que `createClickupTaskForAppUser`/
|
|
357
|
+
* `postSlackMessageForAppUser`.
|
|
358
|
+
*
|
|
359
|
+
* Requires `appSecret` — throws early otherwise, same as
|
|
360
|
+
* `authorizeForAppUser`.
|
|
361
|
+
*
|
|
362
|
+
* @example
|
|
363
|
+
* await af.connectors.saveApiKeyForAppUser('granola', 'grn_xxxxx', {
|
|
364
|
+
* externalUserId: 'scrappydoc-user-42',
|
|
365
|
+
* });
|
|
366
|
+
*/
|
|
367
|
+
saveApiKeyForAppUser(connectorId: string, apiKey: string, input: {
|
|
368
|
+
externalUserId: string;
|
|
369
|
+
}): Promise<{
|
|
370
|
+
connectorId: string;
|
|
371
|
+
}>;
|
|
266
372
|
}
|
|
267
373
|
export interface InboxChannelView {
|
|
268
374
|
id: string;
|
|
@@ -259,8 +259,9 @@ class ConnectorsResource {
|
|
|
259
259
|
* `listConnected()`, which is the ak_live_ tenant-wide picker). Returns
|
|
260
260
|
* the SAME rich shape `listForTenant`/`listForUser` produce server-side
|
|
261
261
|
* (`AppUserConnectorStatus`: name/description/category/iconUrl/configured/
|
|
262
|
-
* accountLabel/connectedAt)
|
|
263
|
-
*
|
|
262
|
+
* accountLabel/connectedAt), PLUS `browsable` (AGF-074, computed
|
|
263
|
+
* server-side on top of the raw `ConnectorStatus` rows) — NOT the narrow
|
|
264
|
+
* `ConnectorStatus` the tenant-picker methods above use.
|
|
264
265
|
*
|
|
265
266
|
* Requires `appSecret` — throws early otherwise, same as
|
|
266
267
|
* `authorizeForAppUser`.
|
|
@@ -301,5 +302,149 @@ class ConnectorsResource {
|
|
|
301
302
|
const params = new URLSearchParams({ externalUserId: input.externalUserId });
|
|
302
303
|
return this.client.request('DELETE', `/connectors/oauth/${encodeURIComponent(connectorId)}/app-user?${params.toString()}`);
|
|
303
304
|
}
|
|
305
|
+
// ─── App-user resource picker (AGF-072d — app-user twin of the picker
|
|
306
|
+
// methods at the top of this file) ──────────────────────────────────────
|
|
307
|
+
//
|
|
308
|
+
// Mirrors listResources/getDefaults/updateDefaults/createClickupTask/
|
|
309
|
+
// postSlackMessage above, scoped to (appId-from-secret, externalUserId)
|
|
310
|
+
// instead of the ak_live_ tenant. Hits `AppUserResourcePickerController`
|
|
311
|
+
// (`/app-user/connector-resources/*`) — a DISTINCT base path from the
|
|
312
|
+
// tenant picker's `/connector-resources/*`, not just a query-param
|
|
313
|
+
// variant. Same auth rule as the 3 methods above: requires `appSecret`,
|
|
314
|
+
// uses `this.client.request()` directly (not `requestWithApiKey()`).
|
|
315
|
+
//
|
|
316
|
+
// NOT mirrored here:
|
|
317
|
+
// - list-connected (`GET /app-user/connector-resources`): its
|
|
318
|
+
// `{connectorId,connected,browsable}[]` shape is a narrower duplicate
|
|
319
|
+
// of what `listConnectorsForAppUser()` above already returns (the
|
|
320
|
+
// richer `AppUserConnectorStatus[]` from
|
|
321
|
+
// `/connectors/oauth/app-user/directory`). Adding a second, thinner
|
|
322
|
+
// "list connected" would just invite callers to pick the wrong one.
|
|
323
|
+
// - disconnect (`DELETE /app-user/connector-resources/:connectorId`):
|
|
324
|
+
// redundant with `disconnectForAppUser()` above
|
|
325
|
+
// (`/connectors/oauth/:id/app-user`) — same ConnectorAuth row, same
|
|
326
|
+
// method name would collide. Use the existing one.
|
|
327
|
+
/**
|
|
328
|
+
* `GET /app-user/connector-resources/:connectorId?externalUserId=...` —
|
|
329
|
+
* real resource browsing (Slack channels, GitHub repos, ClickUp lists…)
|
|
330
|
+
* scoped to ONE end user's OWN grant. App-user counterpart of
|
|
331
|
+
* `listResources()` above — same return shape, same `unsupported: true`
|
|
332
|
+
* behavior for connectors without a resource selector implemented yet.
|
|
333
|
+
*
|
|
334
|
+
* Requires `appSecret` — throws early otherwise, same as
|
|
335
|
+
* `authorizeForAppUser`.
|
|
336
|
+
*
|
|
337
|
+
* @example
|
|
338
|
+
* const { items } = await af.connectors.listResourcesForAppUser('slack', {
|
|
339
|
+
* externalUserId: 'scrappydoc-user-42',
|
|
340
|
+
* });
|
|
341
|
+
*/
|
|
342
|
+
async listResourcesForAppUser(connectorId, input) {
|
|
343
|
+
if (!this.client.getAppSecret()) {
|
|
344
|
+
throw new Error('connectors.listResourcesForAppUser requires appSecret (sk_live_/sk_test_) in ' +
|
|
345
|
+
'AgentForgeClient. This surface authenticates AS the App, not via chatToken/apiKey.');
|
|
346
|
+
}
|
|
347
|
+
const params = new URLSearchParams({ externalUserId: input.externalUserId });
|
|
348
|
+
return this.client.request('GET', `/app-user/connector-resources/${encodeURIComponent(connectorId)}?${params.toString()}`);
|
|
349
|
+
}
|
|
350
|
+
/**
|
|
351
|
+
* `GET /app-user/connector-resources/:connectorId/defaults?externalUserId=...`
|
|
352
|
+
* — tool permissions for this connector, resolved with the App's own
|
|
353
|
+
* override always live (tier 0, `af_app_connectors`) since `appId` comes
|
|
354
|
+
* from the secret. App-user counterpart of `getDefaults()` above.
|
|
355
|
+
* `externalUserId` doesn't affect resolution (defaults are per-App, not
|
|
356
|
+
* per-end-user) — still required because the platform route always reads
|
|
357
|
+
* it off the scope helper shared by this controller's other routes.
|
|
358
|
+
*
|
|
359
|
+
* Requires `appSecret` — throws early otherwise, same as
|
|
360
|
+
* `authorizeForAppUser`.
|
|
361
|
+
*/
|
|
362
|
+
async getDefaultsForAppUser(connectorId, input) {
|
|
363
|
+
if (!this.client.getAppSecret()) {
|
|
364
|
+
throw new Error('connectors.getDefaultsForAppUser requires appSecret (sk_live_/sk_test_) in ' +
|
|
365
|
+
'AgentForgeClient. This surface authenticates AS the App, not via chatToken/apiKey.');
|
|
366
|
+
}
|
|
367
|
+
const params = new URLSearchParams({ externalUserId: input.externalUserId });
|
|
368
|
+
return this.client.request('GET', `/app-user/connector-resources/${encodeURIComponent(connectorId)}/defaults?${params.toString()}`);
|
|
369
|
+
}
|
|
370
|
+
/**
|
|
371
|
+
* `PUT /app-user/connector-resources/:connectorId/defaults?externalUserId=...`
|
|
372
|
+
* — overwrites the connector's tool permissions. App-user counterpart of
|
|
373
|
+
* `updateDefaults()` above. NOTE (mirrors the platform controller's own
|
|
374
|
+
* doc comment): this write lands on the tenant-level row
|
|
375
|
+
* (`af_connector_tool_defaults`), same as the ak_live_ route — there's no
|
|
376
|
+
* App-scoped-only override write today. `externalUserId` travels as a
|
|
377
|
+
* query param (matching `getDefaultsForAppUser`); the platform route also
|
|
378
|
+
* accepts it in the body but query is canonical for this SDK's GET/PUT
|
|
379
|
+
* pair.
|
|
380
|
+
*
|
|
381
|
+
* Requires `appSecret` — throws early otherwise, same as
|
|
382
|
+
* `authorizeForAppUser`.
|
|
383
|
+
*/
|
|
384
|
+
async updateDefaultsForAppUser(connectorId, permissions, input) {
|
|
385
|
+
if (!this.client.getAppSecret()) {
|
|
386
|
+
throw new Error('connectors.updateDefaultsForAppUser requires appSecret (sk_live_/sk_test_) in ' +
|
|
387
|
+
'AgentForgeClient. This surface authenticates AS the App, not via chatToken/apiKey.');
|
|
388
|
+
}
|
|
389
|
+
const params = new URLSearchParams({ externalUserId: input.externalUserId });
|
|
390
|
+
return this.client.request('PUT', `/app-user/connector-resources/${encodeURIComponent(connectorId)}/defaults?${params.toString()}`, { permissions });
|
|
391
|
+
}
|
|
392
|
+
/**
|
|
393
|
+
* `POST /app-user/connector-resources/clickup/tasks` — creates a REAL
|
|
394
|
+
* ClickUp task using the end user's OWN grant. App-user counterpart of
|
|
395
|
+
* `createClickupTask()` above. Unlike the GET/PUT methods above,
|
|
396
|
+
* `externalUserId` travels in the BODY here — the platform route reads it
|
|
397
|
+
* off `body.externalUserId` for this action endpoint (not a query param).
|
|
398
|
+
*
|
|
399
|
+
* Requires `appSecret` — throws early otherwise, same as
|
|
400
|
+
* `authorizeForAppUser`.
|
|
401
|
+
*/
|
|
402
|
+
async createClickupTaskForAppUser(input) {
|
|
403
|
+
if (!this.client.getAppSecret()) {
|
|
404
|
+
throw new Error('connectors.createClickupTaskForAppUser requires appSecret (sk_live_/sk_test_) in ' +
|
|
405
|
+
'AgentForgeClient. This surface authenticates AS the App, not via chatToken/apiKey.');
|
|
406
|
+
}
|
|
407
|
+
return this.client.request('POST', '/app-user/connector-resources/clickup/tasks', input);
|
|
408
|
+
}
|
|
409
|
+
/**
|
|
410
|
+
* `POST /app-user/connector-resources/slack/messages` — posts a REAL
|
|
411
|
+
* Slack message using the end user's OWN grant. App-user counterpart of
|
|
412
|
+
* `postSlackMessage()` above. `externalUserId` travels in the BODY, same
|
|
413
|
+
* as `createClickupTaskForAppUser` (the platform route reads
|
|
414
|
+
* `body.externalUserId` for both action endpoints).
|
|
415
|
+
*
|
|
416
|
+
* Requires `appSecret` — throws early otherwise, same as
|
|
417
|
+
* `authorizeForAppUser`.
|
|
418
|
+
*/
|
|
419
|
+
async postSlackMessageForAppUser(input) {
|
|
420
|
+
if (!this.client.getAppSecret()) {
|
|
421
|
+
throw new Error('connectors.postSlackMessageForAppUser requires appSecret (sk_live_/sk_test_) in ' +
|
|
422
|
+
'AgentForgeClient. This surface authenticates AS the App, not via chatToken/apiKey.');
|
|
423
|
+
}
|
|
424
|
+
return this.client.request('POST', '/app-user/connector-resources/slack/messages', input);
|
|
425
|
+
}
|
|
426
|
+
/**
|
|
427
|
+
* `POST /app-user/connector-resources/:connectorId/api-key` — guarda un
|
|
428
|
+
* API key pegado por el end user, para SU PROPIO grant (no el tenant del
|
|
429
|
+
* App). App-user counterpart of `saveApiKeyForTenant()` above, para
|
|
430
|
+
* connectors que NO usan OAuth (Granola, Mapbox). `externalUserId` viaja
|
|
431
|
+
* en el BODY, mismo patrón que `createClickupTaskForAppUser`/
|
|
432
|
+
* `postSlackMessageForAppUser`.
|
|
433
|
+
*
|
|
434
|
+
* Requires `appSecret` — throws early otherwise, same as
|
|
435
|
+
* `authorizeForAppUser`.
|
|
436
|
+
*
|
|
437
|
+
* @example
|
|
438
|
+
* await af.connectors.saveApiKeyForAppUser('granola', 'grn_xxxxx', {
|
|
439
|
+
* externalUserId: 'scrappydoc-user-42',
|
|
440
|
+
* });
|
|
441
|
+
*/
|
|
442
|
+
async saveApiKeyForAppUser(connectorId, apiKey, input) {
|
|
443
|
+
if (!this.client.getAppSecret()) {
|
|
444
|
+
throw new Error('connectors.saveApiKeyForAppUser requires appSecret (sk_live_/sk_test_) in ' +
|
|
445
|
+
'AgentForgeClient. This surface authenticates AS the App, not via chatToken/apiKey.');
|
|
446
|
+
}
|
|
447
|
+
return this.client.request('POST', `/app-user/connector-resources/${encodeURIComponent(connectorId)}/api-key`, { apiKey, externalUserId: input.externalUserId });
|
|
448
|
+
}
|
|
304
449
|
}
|
|
305
450
|
exports.ConnectorsResource = ConnectorsResource;
|
package/dist/types.d.ts
CHANGED
|
@@ -330,6 +330,11 @@ export interface AppUserConnectorStatus {
|
|
|
330
330
|
configured: boolean;
|
|
331
331
|
/** Este externalUserId particular ya completó el OAuth/API-key setup. */
|
|
332
332
|
connected: boolean;
|
|
333
|
+
/** ¿Tiene selector de recursos real implementado (nivel 2 del picker)?
|
|
334
|
+
* `false` = se puede conectar pero `listResourcesForAppUser()` devuelve
|
|
335
|
+
* `unsupported: true`. Mismo criterio (`SUPPORTED_CONNECTORS`) que
|
|
336
|
+
* `ConnectorStatus.browsable` usa para el picker tenant-wide. */
|
|
337
|
+
browsable: boolean;
|
|
333
338
|
accountLabel?: string;
|
|
334
339
|
/** ISO 8601 — `Date` en el server, serializado a string sobre JSON. */
|
|
335
340
|
connectedAt?: string;
|
|
@@ -338,12 +343,24 @@ export interface ConnectorResourceItem {
|
|
|
338
343
|
id: string;
|
|
339
344
|
name: string;
|
|
340
345
|
description?: string;
|
|
346
|
+
/** Avatar/icon URL for the resource — populated for Slack DMs/people
|
|
347
|
+
* (AGF-074 bug #2: the interlocutor's profile photo, from
|
|
348
|
+
* `users.info`/`users.list`). Channels and other resource kinds leave
|
|
349
|
+
* this `undefined`; render a generic icon (`#` for Slack channels)
|
|
350
|
+
* as a fallback. */
|
|
351
|
+
imageUrl?: string;
|
|
341
352
|
}
|
|
342
353
|
export interface ListConnectorResourcesResult {
|
|
343
354
|
items: ConnectorResourceItem[];
|
|
344
355
|
/** true cuando el connector está conectado pero `browsable` es false —
|
|
345
356
|
* no es un error, la UI debe mostrar un estado "sin selector todavía". */
|
|
346
357
|
unsupported?: true;
|
|
358
|
+
/** AGF-074 bug #3: true cuando el provider devolvió `missing_scope` para
|
|
359
|
+
* un sub-recurso opcional (ej. Slack DMs vía `im`/`mpim`/`users.list`,
|
|
360
|
+
* en un grant OAuth previo a que el connector declarara esos scopes).
|
|
361
|
+
* `items` igual trae lo que SÍ se pudo listar (ej. los canales); la UI
|
|
362
|
+
* debe ofrecer un CTA de reconectar en vez de tratarlo como error. */
|
|
363
|
+
needsReconnectForDms?: true;
|
|
347
364
|
}
|
|
348
365
|
export interface CreateClickupTaskInput {
|
|
349
366
|
/** Id de la lista de ClickUp (`ConnectorResourceItem.id` del picker). */
|
package/package.json
CHANGED