@agentforge-io/sdk-server 4.0.22 → 4.2.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/index.d.ts +1 -1
- package/dist/resources/chat.d.ts +47 -0
- package/dist/resources/chat.js +80 -0
- package/dist/resources/connectors.d.ts +68 -1
- package/dist/resources/connectors.js +101 -3
- package/dist/types.d.ts +15 -0
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ export { AgentForgeClient } from './client';
|
|
|
2
2
|
export type { AgentForgeClientOptions, RequestOptions } from './client';
|
|
3
3
|
export { AgentForgeError, AgentForgeAuthError, AgentForgeNotFoundError, AgentForgeNetworkError, } from './errors';
|
|
4
4
|
export { TOOL_CALLBACK_HEADERS, ToolCallbackSignatureError, signToolCallbackPayload, verifyToolCallbackSignature, } from './webhooks';
|
|
5
|
-
export type { AgentMe, AgentSummary, ApprovalCopyBundle, ChatStreamChunk, ChatStreamEvent, ChatTokenRecord, ConnectorDefaultsResult, ConnectorDefaultsSource, ConnectorResourceItem, ConnectorStatus, ConnectorToolInfo, ConversationHistory, ConversationStatus, CreateAgentInput, CreateClickupTaskInput, CreateClickupTaskResult, ExternalToolSummary, IssueChatTokenInput, ListAgentsResult, ListConnectorResourcesResult, McpServerConfig, MessageRecord, MessageRole, PublicAppBranding, AppSelf, AppSelfConnector, AppSelfConnectors, RegisterToolInput, RegisterToolsInput, RegisterToolsResult, ToolCallbackPayload, ToolCallRecord, ToolPermission, ToolPermissionMode, TokenUsage, TenantSecretEntry, UpdateAgentInput, } from './types';
|
|
5
|
+
export type { AgentMe, AgentSummary, AppUserConnectorStatus, ApprovalCopyBundle, ChatStreamChunk, ChatStreamEvent, ChatTokenRecord, ConnectorDefaultsResult, ConnectorDefaultsSource, ConnectorResourceItem, ConnectorStatus, ConnectorToolInfo, ConversationHistory, ConversationStatus, CreateAgentInput, CreateClickupTaskInput, CreateClickupTaskResult, ExternalToolSummary, IssueChatTokenInput, ListAgentsResult, ListConnectorResourcesResult, McpServerConfig, MessageRecord, MessageRole, PublicAppBranding, AppSelf, AppSelfConnector, AppSelfConnectors, RegisterToolInput, RegisterToolsInput, RegisterToolsResult, ToolCallbackPayload, ToolCallRecord, ToolPermission, ToolPermissionMode, TokenUsage, TenantSecretEntry, UpdateAgentInput, } from './types';
|
|
6
6
|
export { AgentsResource } from './resources/agents';
|
|
7
7
|
export { AppsResource } from './resources/apps';
|
|
8
8
|
export { ChatResource } from './resources/chat';
|
package/dist/resources/chat.d.ts
CHANGED
|
@@ -9,6 +9,20 @@ export interface StreamMessageInput {
|
|
|
9
9
|
/** Si se omite, el server crea una conversación nueva. */
|
|
10
10
|
conversationId?: string;
|
|
11
11
|
}
|
|
12
|
+
export interface StreamMessageForAppUserInput {
|
|
13
|
+
/** Which of the App's tenant agents to run. */
|
|
14
|
+
agentId: string;
|
|
15
|
+
/** The App's own identifier for its end user — NOT signed, rides as a
|
|
16
|
+
* plain param inside the sk_live_-authenticated request (AGF-072 §4.4
|
|
17
|
+
* rationale: the authenticated channel is the proof, not a per-user
|
|
18
|
+
* signature). Threads into the conversation key
|
|
19
|
+
* `app-user:${appId}:${externalUserId}` server-side; `appId` itself is
|
|
20
|
+
* never a param, only ever resolved from the secret. */
|
|
21
|
+
externalUserId: string;
|
|
22
|
+
content: string;
|
|
23
|
+
/** Si se omite, el server crea una conversación nueva. */
|
|
24
|
+
conversationId?: string;
|
|
25
|
+
}
|
|
12
26
|
export declare class ChatResource {
|
|
13
27
|
private readonly client;
|
|
14
28
|
constructor(client: AgentForgeClient);
|
|
@@ -52,4 +66,37 @@ export declare class ChatResource {
|
|
|
52
66
|
* no pertenece al ChatToken que llama.
|
|
53
67
|
*/
|
|
54
68
|
getHistory(conversationId: string): Promise<ConversationHistory>;
|
|
69
|
+
/**
|
|
70
|
+
* AGF-073a — chat streaming AGENT-AWARE para el surface App-authenticated
|
|
71
|
+
* (`sk_live_`/`sk_test_`), server-to-server — `POST
|
|
72
|
+
* /api/v1/app-user-chat/conversations/stream` (o `.../conversations/:id/
|
|
73
|
+
* messages/stream` cuando `input.conversationId` viene seteado). Sibling
|
|
74
|
+
* ADITIVO de `streamMessage()`: NO usa ChatToken, requiere que el
|
|
75
|
+
* `AgentForgeClient` se haya construido con `appSecret`. `appId` lo
|
|
76
|
+
* resuelve el server exclusivamente del secret — nunca es un param acá
|
|
77
|
+
* tampoco (ver `APP_USER_CHAT_RUNTIME_SDD.md`).
|
|
78
|
+
*
|
|
79
|
+
* Mismo shape de eventos que `streamMessage()` — `ChatStreamEvent` con
|
|
80
|
+
* los mismos `kind`s (`conversation` | `chunk` | `stream_end` | `error`).
|
|
81
|
+
* Un consumidor no puede distinguir cuál de los dos métodos produjo el
|
|
82
|
+
* stream a partir de los eventos solos.
|
|
83
|
+
*
|
|
84
|
+
* @example
|
|
85
|
+
* const af = new AgentForgeClient({ baseURL, appSecret: 'sk_live_...' });
|
|
86
|
+
* for await (const ev of af.chat.streamMessageForAppUser({
|
|
87
|
+
* agentId: 'agent-uuid',
|
|
88
|
+
* externalUserId: 'scrappydoc-user-42',
|
|
89
|
+
* content: 'hola',
|
|
90
|
+
* })) {
|
|
91
|
+
* if (ev.kind === 'conversation') conversationId = ev.conversationId;
|
|
92
|
+
* }
|
|
93
|
+
*/
|
|
94
|
+
streamMessageForAppUser(input: StreamMessageForAppUserInput): AsyncGenerator<ChatStreamEvent>;
|
|
95
|
+
/**
|
|
96
|
+
* AGF-073a companion to `streamMessageForAppUser` — historial completo de
|
|
97
|
+
* una conversación app-user, `GET /api/v1/app-user-chat/conversations/:id/
|
|
98
|
+
* messages?externalUserId=...`. `externalUserId` va como query param
|
|
99
|
+
* porque GET no lleva body; `appId` sigue resolviéndose del secret.
|
|
100
|
+
*/
|
|
101
|
+
getHistoryForAppUser(conversationId: string, externalUserId: string): Promise<ConversationHistory>;
|
|
55
102
|
}
|
package/dist/resources/chat.js
CHANGED
|
@@ -110,6 +110,86 @@ class ChatResource {
|
|
|
110
110
|
async getHistory(conversationId) {
|
|
111
111
|
return this.client.request('GET', `/api/v1/chat/conversations/${encodeURIComponent(conversationId)}/messages`);
|
|
112
112
|
}
|
|
113
|
+
/**
|
|
114
|
+
* AGF-073a — chat streaming AGENT-AWARE para el surface App-authenticated
|
|
115
|
+
* (`sk_live_`/`sk_test_`), server-to-server — `POST
|
|
116
|
+
* /api/v1/app-user-chat/conversations/stream` (o `.../conversations/:id/
|
|
117
|
+
* messages/stream` cuando `input.conversationId` viene seteado). Sibling
|
|
118
|
+
* ADITIVO de `streamMessage()`: NO usa ChatToken, requiere que el
|
|
119
|
+
* `AgentForgeClient` se haya construido con `appSecret`. `appId` lo
|
|
120
|
+
* resuelve el server exclusivamente del secret — nunca es un param acá
|
|
121
|
+
* tampoco (ver `APP_USER_CHAT_RUNTIME_SDD.md`).
|
|
122
|
+
*
|
|
123
|
+
* Mismo shape de eventos que `streamMessage()` — `ChatStreamEvent` con
|
|
124
|
+
* los mismos `kind`s (`conversation` | `chunk` | `stream_end` | `error`).
|
|
125
|
+
* Un consumidor no puede distinguir cuál de los dos métodos produjo el
|
|
126
|
+
* stream a partir de los eventos solos.
|
|
127
|
+
*
|
|
128
|
+
* @example
|
|
129
|
+
* const af = new AgentForgeClient({ baseURL, appSecret: 'sk_live_...' });
|
|
130
|
+
* for await (const ev of af.chat.streamMessageForAppUser({
|
|
131
|
+
* agentId: 'agent-uuid',
|
|
132
|
+
* externalUserId: 'scrappydoc-user-42',
|
|
133
|
+
* content: 'hola',
|
|
134
|
+
* })) {
|
|
135
|
+
* if (ev.kind === 'conversation') conversationId = ev.conversationId;
|
|
136
|
+
* }
|
|
137
|
+
*/
|
|
138
|
+
async *streamMessageForAppUser(input) {
|
|
139
|
+
if (!this.client.getAppSecret()) {
|
|
140
|
+
throw new Error('chat.streamMessageForAppUser requires appSecret (sk_live_/sk_test_) in ' +
|
|
141
|
+
'AgentForgeClient. This surface authenticates AS the App, not via chatToken.');
|
|
142
|
+
}
|
|
143
|
+
const path = input.conversationId
|
|
144
|
+
? `/api/v1/app-user-chat/conversations/${encodeURIComponent(input.conversationId)}/messages/stream`
|
|
145
|
+
: '/api/v1/app-user-chat/conversations/stream';
|
|
146
|
+
const res = await this.client.requestStream('POST', path, {
|
|
147
|
+
agentId: input.agentId,
|
|
148
|
+
externalUserId: input.externalUserId,
|
|
149
|
+
content: input.content,
|
|
150
|
+
});
|
|
151
|
+
if (!res.body) {
|
|
152
|
+
throw new Error('chat.streamMessageForAppUser: response has no readable body');
|
|
153
|
+
}
|
|
154
|
+
const reader = res.body.getReader();
|
|
155
|
+
const decoder = new TextDecoder();
|
|
156
|
+
let buffer = '';
|
|
157
|
+
try {
|
|
158
|
+
for (;;) {
|
|
159
|
+
const { value, done } = await reader.read();
|
|
160
|
+
if (done)
|
|
161
|
+
break;
|
|
162
|
+
buffer += decoder.decode(value, { stream: true });
|
|
163
|
+
let idx;
|
|
164
|
+
while ((idx = buffer.indexOf('\n\n')) !== -1) {
|
|
165
|
+
const frame = buffer.slice(0, idx);
|
|
166
|
+
buffer = buffer.slice(idx + 2);
|
|
167
|
+
const raw = parseRawSseFrame(frame);
|
|
168
|
+
if (!raw)
|
|
169
|
+
continue;
|
|
170
|
+
const event = toChatStreamEvent(raw);
|
|
171
|
+
if (event)
|
|
172
|
+
yield event;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
finally {
|
|
177
|
+
reader.releaseLock();
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* AGF-073a companion to `streamMessageForAppUser` — historial completo de
|
|
182
|
+
* una conversación app-user, `GET /api/v1/app-user-chat/conversations/:id/
|
|
183
|
+
* messages?externalUserId=...`. `externalUserId` va como query param
|
|
184
|
+
* porque GET no lleva body; `appId` sigue resolviéndose del secret.
|
|
185
|
+
*/
|
|
186
|
+
async getHistoryForAppUser(conversationId, externalUserId) {
|
|
187
|
+
if (!this.client.getAppSecret()) {
|
|
188
|
+
throw new Error('chat.getHistoryForAppUser requires appSecret (sk_live_/sk_test_) in AgentForgeClient.');
|
|
189
|
+
}
|
|
190
|
+
return this.client.request('GET', `/api/v1/app-user-chat/conversations/${encodeURIComponent(conversationId)}/messages` +
|
|
191
|
+
`?externalUserId=${encodeURIComponent(externalUserId)}`);
|
|
192
|
+
}
|
|
113
193
|
}
|
|
114
194
|
exports.ChatResource = ChatResource;
|
|
115
195
|
/** Frame SSE genérico: `event: <name>\ndata: <line>\ndata: <line>...`.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { AgentForgeClient } from '../client';
|
|
2
|
-
import type { ConnectorDefaultsResult, ConnectorStatus, CreateClickupTaskInput, CreateClickupTaskResult, ListConnectorResourcesResult, ToolPermission } from '../types';
|
|
2
|
+
import type { AppUserConnectorStatus, ConnectorDefaultsResult, ConnectorStatus, CreateClickupTaskInput, CreateClickupTaskResult, ListConnectorResourcesResult, ToolPermission } from '../types';
|
|
3
3
|
export declare class ConnectorsResource {
|
|
4
4
|
private readonly client;
|
|
5
5
|
constructor(client: AgentForgeClient);
|
|
@@ -196,6 +196,73 @@ export declare class ConnectorsResource {
|
|
|
196
196
|
* desconecta un canal del inbox omnicanal.
|
|
197
197
|
*/
|
|
198
198
|
destroyInboxChannel(agentId: string, channelId: string): Promise<void>;
|
|
199
|
+
/**
|
|
200
|
+
* `POST /connectors/oauth/:id/authorize-for-app-user` — starts the
|
|
201
|
+
* connector OAuth flow on behalf of ONE end user of the `sk_live_`/
|
|
202
|
+
* `sk_test_` App (`appId` resolved from the secret, `externalUserId`
|
|
203
|
+
* explicit). App-user counterpart of `authorizeForTenant()` above — same
|
|
204
|
+
* response shape (`{ url }`, open it e.g. via `window.open` in the
|
|
205
|
+
* consumer app), same callback flow end-to-end on the platform.
|
|
206
|
+
*
|
|
207
|
+
* Requires the `AgentForgeClient` to have been constructed with
|
|
208
|
+
* `appSecret` — throws early otherwise (this surface authenticates AS the
|
|
209
|
+
* App, not via ak_live_/ChatToken).
|
|
210
|
+
*
|
|
211
|
+
* @example
|
|
212
|
+
* const af = new AgentForgeClient({ baseURL, appSecret: 'sk_live_...' });
|
|
213
|
+
* const { url } = await af.connectors.authorizeForAppUser('slack', {
|
|
214
|
+
* externalUserId: 'scrappydoc-user-42',
|
|
215
|
+
* postAuthRedirect: 'https://myapp.com/settings',
|
|
216
|
+
* });
|
|
217
|
+
*/
|
|
218
|
+
authorizeForAppUser(connectorId: string, input: {
|
|
219
|
+
externalUserId: string;
|
|
220
|
+
postAuthRedirect?: string;
|
|
221
|
+
}): Promise<{
|
|
222
|
+
url: string;
|
|
223
|
+
}>;
|
|
224
|
+
/**
|
|
225
|
+
* `GET /connectors/oauth/app-user/directory` — the given end user's
|
|
226
|
+
* connectors + connection status (App-user counterpart of
|
|
227
|
+
* `listConnected()`, which is the ak_live_ tenant-wide picker). Returns
|
|
228
|
+
* the SAME rich shape `listForTenant`/`listForUser` produce server-side
|
|
229
|
+
* (`AppUserConnectorStatus`: name/description/category/iconUrl/configured/
|
|
230
|
+
* accountLabel/connectedAt) — NOT the narrow `ConnectorStatus` the
|
|
231
|
+
* tenant-picker methods above use.
|
|
232
|
+
*
|
|
233
|
+
* Requires `appSecret` — throws early otherwise, same as
|
|
234
|
+
* `authorizeForAppUser`.
|
|
235
|
+
*
|
|
236
|
+
* @example
|
|
237
|
+
* const { items } = await af.connectors.listConnectorsForAppUser({
|
|
238
|
+
* externalUserId: 'scrappydoc-user-42',
|
|
239
|
+
* });
|
|
240
|
+
* const unconnected = items.filter((c) => c.configured && !c.connected);
|
|
241
|
+
*/
|
|
242
|
+
listConnectorsForAppUser(input: {
|
|
243
|
+
externalUserId: string;
|
|
244
|
+
}): Promise<{
|
|
245
|
+
items: AppUserConnectorStatus[];
|
|
246
|
+
}>;
|
|
247
|
+
/**
|
|
248
|
+
* `DELETE /connectors/oauth/:id/app-user` — disconnects `connectorId` for
|
|
249
|
+
* the given end user. App-user counterpart of `disconnect()` above.
|
|
250
|
+
* Mirrors the platform's `disconnectForAppUser` 404-on-missing behavior
|
|
251
|
+
* (`ConnectorError('not_connected', ...)` → `AgentForgeNotFoundError`).
|
|
252
|
+
*
|
|
253
|
+
* Requires `appSecret` — throws early otherwise, same as
|
|
254
|
+
* `authorizeForAppUser`.
|
|
255
|
+
*
|
|
256
|
+
* @example
|
|
257
|
+
* await af.connectors.disconnectForAppUser('google-drive', {
|
|
258
|
+
* externalUserId: 'scrappydoc-user-42',
|
|
259
|
+
* });
|
|
260
|
+
*/
|
|
261
|
+
disconnectForAppUser(connectorId: string, input: {
|
|
262
|
+
externalUserId: string;
|
|
263
|
+
}): Promise<{
|
|
264
|
+
ok: true;
|
|
265
|
+
}>;
|
|
199
266
|
}
|
|
200
267
|
export interface InboxChannelView {
|
|
201
268
|
id: string;
|
|
@@ -5,9 +5,13 @@
|
|
|
5
5
|
// reales de uno conectado (canales de Slack, repos de GitHub, etc), y arranca
|
|
6
6
|
// el OAuth authorize para uno que falte conectar.
|
|
7
7
|
//
|
|
8
|
-
// Auth:
|
|
9
|
-
// en el server y rechazan ChatToken de plano, aunque el
|
|
10
|
-
// también tenga uno configurado (ver `requestWithApiKey`).
|
|
8
|
+
// Auth: la mayoría de los métodos son ak_live_ tenant-wide — usan
|
|
9
|
+
// `ApiKeyGuard` en el server y rechazan ChatToken de plano, aunque el
|
|
10
|
+
// `AgentForgeClient` también tenga uno configurado (ver `requestWithApiKey`).
|
|
11
|
+
// EXCEPCIÓN (AGF-072, sección "App-user scope" al final del archivo): los
|
|
12
|
+
// métodos `*ForAppUser` (Plane B — un end user del App conectando SU PROPIA
|
|
13
|
+
// cuenta) usan `appSecret` (sk_live_/sk_test_) en vez de ak_live_, y por eso
|
|
14
|
+
// llaman `this.client.request()` directo en lugar de `requestWithApiKey()`.
|
|
11
15
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
16
|
exports.ConnectorsResource = void 0;
|
|
13
17
|
class ConnectorsResource {
|
|
@@ -203,5 +207,99 @@ class ConnectorsResource {
|
|
|
203
207
|
async destroyInboxChannel(agentId, channelId) {
|
|
204
208
|
await this.client.requestWithApiKey('DELETE', `/connectors/inbox/agents/${encodeURIComponent(agentId)}/inbox/channels/${encodeURIComponent(channelId)}`);
|
|
205
209
|
}
|
|
210
|
+
// ─── App-user scope (AGF-072, Option A — APP_END_USER_CONNECTIONS_SDD.md §4.4) ──
|
|
211
|
+
//
|
|
212
|
+
// The 3 methods below are Plane B: a specific END USER of an `sk_live_`/
|
|
213
|
+
// `sk_test_` App connecting THEIR OWN account (their Slack, their Gmail) —
|
|
214
|
+
// distinct from `*ForTenant` above (Plane A, the App's own tenant-wide
|
|
215
|
+
// credentials) and from the ak_live_-only picker methods at the top of this
|
|
216
|
+
// file. Auth is `appSecret` (sk_live_/sk_test_), NOT ak_live_ — these calls
|
|
217
|
+
// use `this.client.request()` directly (plain `authHeaders()`, which picks
|
|
218
|
+
// `appSecret` when set) instead of `requestWithApiKey()`, because that
|
|
219
|
+
// helper hardcodes `forceApiKey: true` and would reject an appSecret-only
|
|
220
|
+
// client. Same pattern as `ChatResource.streamMessageForAppUser`.
|
|
221
|
+
//
|
|
222
|
+
// `appId` is NEVER a param on any of these — the platform resolves it
|
|
223
|
+
// exclusively from the `sk_live_`/`sk_test_` secret server-side (SDD §4.4),
|
|
224
|
+
// so App Y's secret can never touch App X's grants no matter what
|
|
225
|
+
// `externalUserId` is passed. Only `externalUserId` (the App's own,
|
|
226
|
+
// unsigned identifier for its end user) travels as a param.
|
|
227
|
+
/**
|
|
228
|
+
* `POST /connectors/oauth/:id/authorize-for-app-user` — starts the
|
|
229
|
+
* connector OAuth flow on behalf of ONE end user of the `sk_live_`/
|
|
230
|
+
* `sk_test_` App (`appId` resolved from the secret, `externalUserId`
|
|
231
|
+
* explicit). App-user counterpart of `authorizeForTenant()` above — same
|
|
232
|
+
* response shape (`{ url }`, open it e.g. via `window.open` in the
|
|
233
|
+
* consumer app), same callback flow end-to-end on the platform.
|
|
234
|
+
*
|
|
235
|
+
* Requires the `AgentForgeClient` to have been constructed with
|
|
236
|
+
* `appSecret` — throws early otherwise (this surface authenticates AS the
|
|
237
|
+
* App, not via ak_live_/ChatToken).
|
|
238
|
+
*
|
|
239
|
+
* @example
|
|
240
|
+
* const af = new AgentForgeClient({ baseURL, appSecret: 'sk_live_...' });
|
|
241
|
+
* const { url } = await af.connectors.authorizeForAppUser('slack', {
|
|
242
|
+
* externalUserId: 'scrappydoc-user-42',
|
|
243
|
+
* postAuthRedirect: 'https://myapp.com/settings',
|
|
244
|
+
* });
|
|
245
|
+
*/
|
|
246
|
+
async authorizeForAppUser(connectorId, input) {
|
|
247
|
+
if (!this.client.getAppSecret()) {
|
|
248
|
+
throw new Error('connectors.authorizeForAppUser requires appSecret (sk_live_/sk_test_) in ' +
|
|
249
|
+
'AgentForgeClient. This surface authenticates AS the App, not via chatToken/apiKey.');
|
|
250
|
+
}
|
|
251
|
+
const params = new URLSearchParams({ externalUserId: input.externalUserId });
|
|
252
|
+
if (input.postAuthRedirect)
|
|
253
|
+
params.set('postAuthRedirect', input.postAuthRedirect);
|
|
254
|
+
return this.client.request('POST', `/connectors/oauth/${encodeURIComponent(connectorId)}/authorize-for-app-user?${params.toString()}`);
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* `GET /connectors/oauth/app-user/directory` — the given end user's
|
|
258
|
+
* connectors + connection status (App-user counterpart of
|
|
259
|
+
* `listConnected()`, which is the ak_live_ tenant-wide picker). Returns
|
|
260
|
+
* the SAME rich shape `listForTenant`/`listForUser` produce server-side
|
|
261
|
+
* (`AppUserConnectorStatus`: name/description/category/iconUrl/configured/
|
|
262
|
+
* accountLabel/connectedAt) — NOT the narrow `ConnectorStatus` the
|
|
263
|
+
* tenant-picker methods above use.
|
|
264
|
+
*
|
|
265
|
+
* Requires `appSecret` — throws early otherwise, same as
|
|
266
|
+
* `authorizeForAppUser`.
|
|
267
|
+
*
|
|
268
|
+
* @example
|
|
269
|
+
* const { items } = await af.connectors.listConnectorsForAppUser({
|
|
270
|
+
* externalUserId: 'scrappydoc-user-42',
|
|
271
|
+
* });
|
|
272
|
+
* const unconnected = items.filter((c) => c.configured && !c.connected);
|
|
273
|
+
*/
|
|
274
|
+
async listConnectorsForAppUser(input) {
|
|
275
|
+
if (!this.client.getAppSecret()) {
|
|
276
|
+
throw new Error('connectors.listConnectorsForAppUser requires appSecret (sk_live_/sk_test_) in ' +
|
|
277
|
+
'AgentForgeClient. This surface authenticates AS the App, not via chatToken/apiKey.');
|
|
278
|
+
}
|
|
279
|
+
const params = new URLSearchParams({ externalUserId: input.externalUserId });
|
|
280
|
+
return this.client.request('GET', `/connectors/oauth/app-user/directory?${params.toString()}`);
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* `DELETE /connectors/oauth/:id/app-user` — disconnects `connectorId` for
|
|
284
|
+
* the given end user. App-user counterpart of `disconnect()` above.
|
|
285
|
+
* Mirrors the platform's `disconnectForAppUser` 404-on-missing behavior
|
|
286
|
+
* (`ConnectorError('not_connected', ...)` → `AgentForgeNotFoundError`).
|
|
287
|
+
*
|
|
288
|
+
* Requires `appSecret` — throws early otherwise, same as
|
|
289
|
+
* `authorizeForAppUser`.
|
|
290
|
+
*
|
|
291
|
+
* @example
|
|
292
|
+
* await af.connectors.disconnectForAppUser('google-drive', {
|
|
293
|
+
* externalUserId: 'scrappydoc-user-42',
|
|
294
|
+
* });
|
|
295
|
+
*/
|
|
296
|
+
async disconnectForAppUser(connectorId, input) {
|
|
297
|
+
if (!this.client.getAppSecret()) {
|
|
298
|
+
throw new Error('connectors.disconnectForAppUser requires appSecret (sk_live_/sk_test_) in ' +
|
|
299
|
+
'AgentForgeClient. This surface authenticates AS the App, not via chatToken/apiKey.');
|
|
300
|
+
}
|
|
301
|
+
const params = new URLSearchParams({ externalUserId: input.externalUserId });
|
|
302
|
+
return this.client.request('DELETE', `/connectors/oauth/${encodeURIComponent(connectorId)}/app-user?${params.toString()}`);
|
|
303
|
+
}
|
|
206
304
|
}
|
|
207
305
|
exports.ConnectorsResource = ConnectorsResource;
|
package/dist/types.d.ts
CHANGED
|
@@ -319,6 +319,21 @@ export interface ConnectorStatus {
|
|
|
319
319
|
* false = se puede conectar pero `listResources()` devuelve `unsupported`. */
|
|
320
320
|
browsable: boolean;
|
|
321
321
|
}
|
|
322
|
+
export interface AppUserConnectorStatus {
|
|
323
|
+
connectorId: string;
|
|
324
|
+
name: string;
|
|
325
|
+
description: string;
|
|
326
|
+
category?: string;
|
|
327
|
+
iconUrl?: string;
|
|
328
|
+
/** El operador del tenant ya trajo credenciales para este provider. Si es
|
|
329
|
+
* `false`, este end user no puede conectar todavía (falta setup admin). */
|
|
330
|
+
configured: boolean;
|
|
331
|
+
/** Este externalUserId particular ya completó el OAuth/API-key setup. */
|
|
332
|
+
connected: boolean;
|
|
333
|
+
accountLabel?: string;
|
|
334
|
+
/** ISO 8601 — `Date` en el server, serializado a string sobre JSON. */
|
|
335
|
+
connectedAt?: string;
|
|
336
|
+
}
|
|
322
337
|
export interface ConnectorResourceItem {
|
|
323
338
|
id: string;
|
|
324
339
|
name: string;
|
package/package.json
CHANGED