@alfe.ai/agent-api-client 0.1.3 → 0.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.cjs CHANGED
@@ -116,41 +116,362 @@ var AgentApiClient = class {
116
116
  async getRegistry() {
117
117
  return this.request("/integrations/registry");
118
118
  }
119
+ /**
120
+ * Returns every connected Google account for the agent. Multi-account by
121
+ * design — the openclaw-google plugin requires the LLM to pass `email`
122
+ * explicitly to `google_run_command` so an account is always selected
123
+ * deliberately.
124
+ *
125
+ * 2026-05-14 (connections-redesign PR 1): the legacy flat shape (`email`,
126
+ * `refreshToken`, `accessToken`, etc., populated from the default account)
127
+ * is gone. Iterate over `accounts`.
128
+ */
119
129
  async getGoogleCredentials() {
120
- return this.request("/agent/google/credentials");
130
+ return { accounts: (await this.request("/agent/connect/google/accounts")).accounts.map((a) => ({
131
+ email: a.accountIdentifier,
132
+ refreshToken: a.refreshToken ?? "",
133
+ clientId: a.clientId ?? "",
134
+ clientSecret: a.clientSecret ?? "",
135
+ displayName: a.displayName ?? void 0,
136
+ connectedAt: a.connectedAt
137
+ })) };
121
138
  }
122
139
  async disconnectGoogleAccount(email) {
123
- return this.request(`/agent/google/accounts/${encodeURIComponent(email)}`, { method: "DELETE" });
124
- }
125
- async setDefaultGoogleAccount(email) {
126
- return this.request(`/agent/google/accounts/${encodeURIComponent(email)}/default`, { method: "PUT" });
140
+ return { accounts: (await this.request(`/agent/connect/google/accounts/${encodeURIComponent(email)}`, { method: "DELETE" })).accounts.map((a) => ({
141
+ email: a.accountIdentifier,
142
+ displayName: a.displayName ?? void 0,
143
+ connectedAt: a.connectedAt
144
+ })) };
127
145
  }
128
146
  async getGoogleChatCredentials() {
129
147
  return this.request("/agent/google-chat/credentials");
130
148
  }
149
+ /**
150
+ * @deprecated Returns a single primary credential blob (legacy "pick-the-
151
+ * default-connection" shape). Use `getGithubAccounts()` for the multi-
152
+ * account shape required by Pattern A — explicit selector args on every
153
+ * tool. Retained because the `@alfe.ai/openclaw-github` proxy is the
154
+ * only consumer that knows about Pattern A; legacy env-interpolation
155
+ * callers will keep hitting `/credentials` until they move to the proxy.
156
+ */
131
157
  async getGithubCredentials() {
132
- return this.request("/agent/github/credentials");
158
+ const raw = await this.request("/agent/connect/github/credentials");
159
+ return {
160
+ login: raw.login,
161
+ accessToken: raw.accessToken
162
+ };
133
163
  }
164
+ /**
165
+ * Pattern A: multi-account credential fetch for GitHub.
166
+ *
167
+ * Returns every agent-scoped GitHub connection. The caller is expected
168
+ * to require a `login` selector on every credential-touching tool and
169
+ * look up the matching account at dispatch time.
170
+ *
171
+ * GitHub OAuth tokens have no expiry (`tokenLifecycle: "no_expiry"`),
172
+ * so there is intentionally no `refreshGithubAccountToken` method — if
173
+ * a token is revoked the user must re-run the OAuth flow.
174
+ *
175
+ * Returned `accounts[i].login` is the GitHub username — the stable
176
+ * cross-session identifier the LLM should pass.
177
+ */
178
+ async getGithubAccounts() {
179
+ return { accounts: (await this.request("/agent/connect/github/accounts")).accounts.map((a) => ({
180
+ connectionId: a.connectionId,
181
+ accountIdentifier: a.accountIdentifier,
182
+ displayName: a.displayName,
183
+ connectedAt: a.connectedAt,
184
+ accessToken: a.accessToken ?? "",
185
+ login: a.login ?? a.accountIdentifier,
186
+ scopes: a.scopes ?? ""
187
+ })) };
188
+ }
189
+ /**
190
+ * @deprecated Returns a single primary credential blob (legacy "pick-the-
191
+ * default-connection" shape). Use `getXeroAccounts()` for the multi-
192
+ * account shape required by Pattern A — explicit selector args on every
193
+ * tool. This method will be removed once all consumers migrate.
194
+ */
134
195
  async getXeroCredentials() {
135
- return this.request("/agent/xero/credentials");
196
+ const raw = await this.request("/agent/connect/xero/credentials");
197
+ return {
198
+ accessToken: raw.accessToken,
199
+ accessTokenExpiresAt: raw.accessTokenExpiresAt ?? "",
200
+ xeroTenantId: raw.xeroTenantId ?? ""
201
+ };
202
+ }
203
+ /**
204
+ * Pattern A: multi-account credential fetch for Xero. Returns every
205
+ * agent-scoped Xero connection. The caller is expected to require a
206
+ * selector arg (e.g. `xeroTenantId`) on every credential-touching tool
207
+ * and look up the matching account by that selector at dispatch time.
208
+ *
209
+ * Returned `accounts[i].accountIdentifier` is the Xero tenantId — the
210
+ * stable cross-session identifier the LLM should pass.
211
+ */
212
+ async getXeroAccounts() {
213
+ return { accounts: (await this.request("/agent/connect/xero/accounts")).accounts.map((a) => ({
214
+ connectionId: a.connectionId,
215
+ accountIdentifier: a.accountIdentifier,
216
+ displayName: a.displayName,
217
+ connectedAt: a.connectedAt,
218
+ accessToken: a.accessToken,
219
+ accessTokenExpiresAt: a.accessTokenExpiresAt ?? "",
220
+ xeroTenantId: a.xeroTenantId ?? a.accountIdentifier
221
+ })) };
136
222
  }
137
223
  async refreshXeroToken() {
138
- return this.request("/agent/xero/token", { method: "POST" });
224
+ return this.request("/agent/connect/xero/refresh", { method: "POST" });
225
+ }
226
+ /**
227
+ * Pattern A: refresh a specific Xero connection by its `accountIdentifier`
228
+ * (the Xero `tenantId`). The legacy `refreshXeroToken()` only refreshes
229
+ * the *primary* connection, which is wrong for multi-tenant Xero where
230
+ * each tenant has its own non-interchangeable access token.
231
+ */
232
+ async refreshXeroAccountToken(xeroTenantId) {
233
+ const path = `/agent/connect/xero/accounts/${encodeURIComponent(xeroTenantId)}/refresh`;
234
+ const raw = await this.request(path, { method: "POST" });
235
+ return {
236
+ accessToken: raw.accessToken,
237
+ accessTokenExpiresAt: raw.accessTokenExpiresAt ?? "",
238
+ expiresAt: raw.expiresAt ?? ""
239
+ };
139
240
  }
241
+ /**
242
+ * @deprecated Returns a single primary credential blob (legacy "pick-the-
243
+ * default-connection" shape). Use `getNotionAccounts()` for the multi-
244
+ * account shape required by Pattern A.
245
+ */
140
246
  async getNotionCredentials() {
141
- return this.request("/agent/notion/credentials");
247
+ const raw = await this.request("/agent/connect/notion/credentials");
248
+ return {
249
+ accessToken: raw.accessToken,
250
+ workspaceId: raw.workspaceId ?? "",
251
+ workspaceName: raw.workspaceName ?? ""
252
+ };
142
253
  }
254
+ /**
255
+ * Pattern A: multi-account credential fetch for Notion. Returns every
256
+ * agent-scoped Notion connection. The caller is expected to require a
257
+ * selector arg (e.g. `workspaceId`) on every credential-touching tool.
258
+ *
259
+ * Returned `accounts[i].accountIdentifier` is the Notion workspaceId.
260
+ */
261
+ async getNotionAccounts() {
262
+ return { accounts: (await this.request("/agent/connect/notion/accounts")).accounts.map((a) => ({
263
+ connectionId: a.connectionId,
264
+ accountIdentifier: a.accountIdentifier,
265
+ displayName: a.displayName,
266
+ connectedAt: a.connectedAt,
267
+ accessToken: a.accessToken,
268
+ workspaceId: a.workspaceId ?? a.accountIdentifier,
269
+ workspaceName: a.workspaceName ?? a.displayName ?? ""
270
+ })) };
271
+ }
272
+ /**
273
+ * @deprecated Returns a single primary Atlassian Connection's credentials
274
+ * (one OAuth user, one cloudId) — the legacy "pick-the-default-connection"
275
+ * shape. Atlassian is multi-site by nature (each OAuth user may have
276
+ * access to multiple Cloud sites), so Pattern A plugins MUST use
277
+ * `getAtlassianAccounts()` to discover the full set and dispatch via
278
+ * the `cloudId` selector arg.
279
+ */
143
280
  async getAtlassianCredentials() {
144
- return this.request("/agent/atlassian/credentials");
281
+ const raw = await this.request("/agent/connect/atlassian/credentials");
282
+ return {
283
+ accessToken: raw.accessToken,
284
+ refreshToken: "",
285
+ accessTokenExpiresAt: raw.accessTokenExpiresAt ?? "",
286
+ cloudId: raw.cloudId ?? "",
287
+ siteName: raw.siteName ?? "",
288
+ siteUrl: raw.siteUrl ?? "",
289
+ email: "",
290
+ enabledProducts: [],
291
+ clientId: raw.clientId,
292
+ clientSecret: raw.clientSecret
293
+ };
145
294
  }
146
295
  async refreshAtlassianToken() {
147
- return this.request("/agent/atlassian/token", { method: "POST" });
296
+ return this.request("/agent/connect/atlassian/refresh", { method: "POST" });
297
+ }
298
+ /**
299
+ * Pattern A: multi-account / multi-site credential fetch for Atlassian.
300
+ *
301
+ * Returns every agent-scoped Atlassian Connection. Each Connection is
302
+ * one OAuth user with a single access token and N accessible Cloud
303
+ * sites (`availableSites`). The caller is expected to:
304
+ *
305
+ * 1. Flatten (connection × cloudId) into one MCP child per site.
306
+ * 2. Require a `cloudId` selector on every credential-touching tool.
307
+ * 3. Use the access token bound to the Connection that owns the
308
+ * requested `cloudId` (Atlassian shares one access token across
309
+ * all sites accessible to the OAuth user).
310
+ *
311
+ * Per-account token refresh uses `refreshAtlassianAccountToken(email)`
312
+ * — refreshing one Connection rotates its single access token, which
313
+ * then applies to every cloudId for that Connection.
314
+ *
315
+ * Returned `accounts[i].accountIdentifier` is the OAuth user's email
316
+ * — the stable cross-session identifier for refresh purposes. The LLM
317
+ * never sees this directly: it picks a site via the `cloudId` arg
318
+ * instead.
319
+ */
320
+ async getAtlassianAccounts() {
321
+ return { accounts: (await this.request("/agent/connect/atlassian/accounts")).accounts.map((a) => ({
322
+ connectionId: a.connectionId,
323
+ accountIdentifier: a.accountIdentifier,
324
+ displayName: a.displayName,
325
+ connectedAt: a.connectedAt,
326
+ accessToken: a.accessToken ?? "",
327
+ accessTokenExpiresAt: a.accessTokenExpiresAt ?? "",
328
+ clientId: a.clientId ?? "",
329
+ clientSecret: a.clientSecret ?? "",
330
+ cloudId: a.cloudId ?? "",
331
+ siteName: a.siteName ?? "",
332
+ siteUrl: a.siteUrl ?? "",
333
+ availableSites: a.availableSites ?? []
334
+ })) };
148
335
  }
336
+ /**
337
+ * Pattern A: refresh a specific Atlassian Connection by `accountIdentifier`
338
+ * (the OAuth user's email).
339
+ *
340
+ * Atlassian rotates refresh tokens (`rotatesRefreshToken: true`); the
341
+ * server-side per-account refresh endpoint handles rotation and
342
+ * persistence. Refreshing one Connection updates its single access
343
+ * token, which applies to every accessible Cloud site (cloudId) for
344
+ * that OAuth user.
345
+ *
346
+ * Returns the new access token + expiry. The proxy is responsible for
347
+ * fanning the new token out to every child server it spawned for
348
+ * cloudIds owned by this Connection.
349
+ */
350
+ async refreshAtlassianAccountToken(accountIdentifier) {
351
+ const path = `/agent/connect/atlassian/accounts/${encodeURIComponent(accountIdentifier)}/refresh`;
352
+ const raw = await this.request(path, { method: "POST" });
353
+ return {
354
+ accessToken: raw.accessToken,
355
+ accessTokenExpiresAt: raw.accessTokenExpiresAt ?? "",
356
+ expiresAt: raw.expiresAt ?? ""
357
+ };
358
+ }
359
+ /**
360
+ * @deprecated Returns a single primary credential blob (legacy "pick-the-
361
+ * default-connection" shape). Use `getMYOBAccounts()` for the multi-
362
+ * account shape required by Pattern A.
363
+ */
149
364
  async getMYOBCredentials() {
150
- return this.request("/agent/myob/credentials");
365
+ const raw = await this.request("/agent/connect/myob/credentials");
366
+ return {
367
+ accessToken: raw.accessToken,
368
+ accessTokenExpiresAt: raw.accessTokenExpiresAt ?? "",
369
+ myobBusinessId: raw.myobBusinessId,
370
+ clientId: raw.clientId
371
+ };
372
+ }
373
+ /**
374
+ * Pattern A: multi-account credential fetch for MYOB. Returns every
375
+ * agent-scoped MYOB connection. The caller is expected to require a
376
+ * selector arg (e.g. `myobBusinessId` / `accountIdentifier`) on every
377
+ * credential-touching tool.
378
+ *
379
+ * Returned `accounts[i].accountIdentifier` is the MYOB businessId.
380
+ */
381
+ async getMYOBAccounts() {
382
+ return { accounts: (await this.request("/agent/connect/myob/accounts")).accounts.map((a) => ({
383
+ connectionId: a.connectionId,
384
+ accountIdentifier: a.accountIdentifier,
385
+ displayName: a.displayName,
386
+ connectedAt: a.connectedAt,
387
+ accessToken: a.accessToken,
388
+ accessTokenExpiresAt: a.accessTokenExpiresAt ?? "",
389
+ myobBusinessId: a.myobBusinessId ?? a.accountIdentifier,
390
+ clientId: a.clientId
391
+ })) };
151
392
  }
152
393
  async refreshMYOBToken() {
153
- return this.request("/agent/myob/token", { method: "POST" });
394
+ return this.request("/agent/connect/myob/refresh", { method: "POST" });
395
+ }
396
+ /**
397
+ * Microsoft 365 (delegated OAuth) credential fetch — single-account shape.
398
+ *
399
+ * @deprecated Use `getMicrosoftAccounts()` and dispatch via the `email`
400
+ * selector once per-account plugins land. Retained because the existing
401
+ * `integrations/connect/microsoft/hooks/post_activate.mjs` writes
402
+ * `mgc` credentials for the single (default) Microsoft account.
403
+ *
404
+ * Returns the agent's effective Microsoft delegated-OAuth credentials.
405
+ * Distinct from `getTeamsCredentials()` (Azure bot credentials for the
406
+ * Teams adapter, which is admin-consent flow on services/microsoft, not
407
+ * delegated OAuth on services/connect).
408
+ */
409
+ async getMicrosoftCredentials() {
410
+ const raw = await this.request("/agent/connect/microsoft/credentials");
411
+ return {
412
+ accessToken: raw.accessToken ?? "",
413
+ accessTokenExpiresAt: raw.accessTokenExpiresAt,
414
+ refreshToken: raw.refreshToken ?? "",
415
+ clientId: raw.clientId ?? "",
416
+ clientSecret: raw.clientSecret ?? "",
417
+ email: raw.email ?? raw.accountIdentifier,
418
+ microsoftTenantId: raw.microsoftTenantId,
419
+ workspaceDomain: raw.workspaceDomain
420
+ };
421
+ }
422
+ /**
423
+ * Pattern A: multi-account credential fetch for Microsoft 365.
424
+ *
425
+ * Returns every agent-scoped Microsoft connection. The caller is expected
426
+ * to require an `email` selector on every credential-touching tool and
427
+ * look up the matching account at dispatch time.
428
+ *
429
+ * Returned `accounts[i].accountIdentifier` is the user's primary email
430
+ * (or the tid claim as fallback) — the stable cross-session identifier
431
+ * the LLM should pass.
432
+ *
433
+ * Per-account token refresh is exposed via `refreshMicrosoftAccountToken`,
434
+ * NOT `refreshXeroAccountToken` — Microsoft refresh tokens are not
435
+ * interchangeable across (tenant, user) pairs.
436
+ */
437
+ async getMicrosoftAccounts() {
438
+ return { accounts: (await this.request("/agent/connect/microsoft/accounts")).accounts.map((a) => ({
439
+ connectionId: a.connectionId,
440
+ accountIdentifier: a.accountIdentifier,
441
+ displayName: a.displayName,
442
+ connectedAt: a.connectedAt,
443
+ accessToken: a.accessToken ?? "",
444
+ accessTokenExpiresAt: a.accessTokenExpiresAt ?? "",
445
+ refreshToken: a.refreshToken ?? "",
446
+ clientId: a.clientId ?? "",
447
+ clientSecret: a.clientSecret ?? "",
448
+ email: a.email ?? a.accountIdentifier,
449
+ microsoftTenantId: a.microsoftTenantId ?? "",
450
+ workspaceDomain: a.workspaceDomain ?? ""
451
+ })) };
452
+ }
453
+ /**
454
+ * Pattern A: refresh a specific Microsoft 365 connection by its
455
+ * `accountIdentifier`. For Microsoft, `accountIdentifier` is the user's
456
+ * email when the Graph profile fetch succeeded at connect time, and the
457
+ * Azure tenant id (`tid` claim) as fallback. Callers should pass the
458
+ * value returned by `getMicrosoftAccounts()` rather than synthesising
459
+ * an email locally.
460
+ *
461
+ * Microsoft refresh tokens are bound to a specific (tenant, user) pair —
462
+ * they are NOT interchangeable across accounts, so per-account refresh
463
+ * is mandatory. The generic /accounts/{accountIdentifier}/refresh
464
+ * endpoint walks the agent's full visible scope chain to find a matching
465
+ * connection (works for inherited team/project Microsoft connections).
466
+ */
467
+ async refreshMicrosoftAccountToken(accountIdentifier) {
468
+ const path = `/agent/connect/microsoft/accounts/${encodeURIComponent(accountIdentifier)}/refresh`;
469
+ const raw = await this.request(path, { method: "POST" });
470
+ return {
471
+ accessToken: raw.accessToken,
472
+ accessTokenExpiresAt: raw.accessTokenExpiresAt ?? "",
473
+ expiresAt: raw.expiresAt ?? ""
474
+ };
154
475
  }
155
476
  async getTeamsCredentials() {
156
477
  return this.request("/agent/microsoft/credentials");