@alfe.ai/openclaw-sync 0.3.14 → 0.3.16

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.cts CHANGED
@@ -1,5 +1,5 @@
1
1
  import plugin, { SyncPluginConfig } from "./plugin.cjs";
2
- import { ChangelogEntry, EncryptedEnvelopeV1, FieldEnvelope, FieldFormat, FieldSensitivity, GeneratedDataKey, IntegrationConfigResult, IntegrationInstall, RegistryEntry, ScopeInfo, SecretAggregate, SecretCategory, SecretMetadata, SecretScope } from "@alfe/types";
2
+ import { ChangelogEntry, EncryptedEnvelopeV1, FieldEnvelope, FieldFormat, FieldSensitivity, GeneratedDataKey, IntegrationActivationSource, IntegrationActualStatus, IntegrationConfigResult, IntegrationDesiredStatus, IntegrationInstall, IntegrationScope, RegistryEntry, ScopeInfo, SecretAggregate, SecretCategory, SecretMetadata, SecretScope } from "@alfe/types";
3
3
 
4
4
  //#region src/manifest.d.ts
5
5
 
@@ -182,1519 +182,1602 @@ declare class ApiBase {
182
182
  }
183
183
  //# sourceMappingURL=transport.d.ts.map
184
184
  //#endregion
185
- //#region src/domains/workspace.d.ts
186
- /** Response of GET /agent/workspace (services/agents). */
187
- interface AgentWorkspaceInfo {
188
- templateKey?: string;
189
- defaultModel?: string;
190
- installedFrom?: {
191
- templateKey: string;
192
- authorTenantId: string;
193
- version: number;
194
- };
195
- runtime?: string;
196
- teams?: {
197
- teamId: string;
198
- name: string;
199
- description?: string;
200
- parentTeamId?: string;
201
- }[];
202
- projects?: {
203
- projectId: string;
204
- name: string;
205
- description?: string;
206
- status: string;
207
- parentProjectId?: string;
208
- }[];
209
- teamIds?: string[];
210
- projectIds?: string[];
185
+ //#region src/domains/connect-credentials.d.ts
186
+ /** Provider projection plus the stable identity of its backing Connection. */
187
+ interface ConnectProviderAccount {
188
+ connectionId: string;
189
+ accountIdentifier: string;
190
+ displayName: string | null;
191
+ connectedAt: string;
192
+ [key: string]: unknown;
193
+ }
194
+ interface ConnectProviderAccounts {
195
+ provider: string;
196
+ accounts: ConnectProviderAccount[];
211
197
  }
212
- declare class WorkspaceApi extends ApiBase {
198
+ declare class ConnectCredentialsApi extends ApiBase {
213
199
  /**
214
- * GET /agent/workspace workspace config for the authenticated agent
215
- * (template assignment, default model, org roster).
200
+ * Discover all active Connections visible to this agent for one provider.
201
+ * Preserve the provider-specific credential projection without guessing a
202
+ * token shape. These rows contain secrets: tool discovery must explicitly
203
+ * select public identity fields, never return/spread the complete response.
204
+ * Use getConnectionCredentials(connectionId) for fresh per-call authority.
216
205
  */
217
- getWorkspace(): Promise<AgentWorkspaceInfo>;
206
+ getConnectProviderAccounts(provider: string): Promise<ConnectProviderAccounts>;
218
207
  /**
219
- * GET /templates/{key}/files persona/workspace file contents for a
220
- * template the agent has access to. Pass `version` to pin to the version
221
- * the agent was installed from (omit the endpoint resolves `latest`).
208
+ * Returns every connected Google account for the agent. Multi-account by
209
+ * design the openclaw-google plugin requires the LLM to pass `email`
210
+ * explicitly to `google_run_command` so an account is always selected
211
+ * deliberately.
212
+ *
213
+ * 2026-05-14 (connections-redesign PR 1): the legacy flat shape (`email`,
214
+ * `refreshToken`, `accessToken`, etc., populated from the default account)
215
+ * is gone. Iterate over `accounts`.
222
216
  */
223
- getTemplateFiles(templateKey: string, opts?: {
224
- version?: number;
225
- }): Promise<{
226
- files: Record<string, string>;
227
- }>;
228
- }
229
- //# sourceMappingURL=workspace.d.ts.map
230
- //#endregion
231
- //#region src/domains/sync.d.ts
232
- interface SyncAgentInfo {
233
- agentId: string;
234
- tenantId: string;
235
- displayName: string;
236
- s3Prefix: string;
237
- status: "stale" | "syncing" | "synced";
238
- fileCount?: number;
239
- totalSize?: number;
240
- lastSync?: string;
241
- }
242
- interface SyncManifestEntry {
243
- hash: string;
244
- size: number;
245
- modified: string;
246
- etag?: string;
247
- storageClass?: string;
248
- compressed?: boolean;
249
- }
250
- interface SyncManifest {
251
- version: 1;
252
- agentId: string;
253
- lastSync: string;
254
- files: Record<string, SyncManifestEntry>;
255
- }
256
- interface SyncPresignedUrl {
257
- path: string;
258
- url: string;
259
- expiresAt: string;
260
- }
261
- interface SyncConfirmedUpload {
262
- filePath: string;
263
- hash: string;
264
- size: number;
265
- storageClass: "STANDARD" | "GLACIER_IR";
266
- syncedAt: string;
267
- }
268
- interface SyncReconstructFile {
269
- path: string;
270
- size: number;
271
- url: string;
272
- storageClass?: string;
273
- compressed?: boolean;
274
- }
275
- interface SyncReconstructBundle {
276
- agentId: string;
277
- mode: "full" | "active" | "memory";
278
- fileCount: number;
279
- totalSize: number;
280
- files: SyncReconstructFile[];
281
- expiresAt: string;
282
- }
283
- interface SyncAgentStats {
284
- agentId: string;
285
- standardBytes: number;
286
- glacierBytes: number;
287
- fileCount: number;
288
- lastSyncAt: string | null;
289
- }
290
- interface SyncFileEntry {
291
- filePath: string;
292
- size: number;
293
- modified: string;
294
- contentHash: string;
295
- storageClass?: string;
296
- compressed?: boolean;
297
- }
298
- interface SyncSessionEntry {
299
- sessionId: string;
300
- size: number;
301
- lastModified: string;
302
- storageClass?: string;
303
- isArchived: boolean;
304
- }
305
- interface SyncSessionContent {
306
- sessionId: string;
307
- content: string;
308
- compressed: boolean;
309
- }
310
- interface SharedFileEntry {
311
- filePath: string;
312
- fileName: string;
313
- size: number;
314
- contentType?: string;
315
- }
316
- declare class SyncApi extends ApiBase {
317
- syncRegister(args?: {
318
- displayName?: string;
319
- }): Promise<{
320
- agent: SyncAgentInfo;
321
- }>;
322
- syncGetManifest(): Promise<SyncManifest>;
323
- syncPresign(args: {
324
- files: {
325
- path: string;
326
- operation: "put" | "get";
327
- contentType?: string;
217
+ getGoogleCredentials(): Promise<{
218
+ accounts: {
219
+ email: string;
220
+ refreshToken: string;
221
+ clientId: string;
222
+ clientSecret: string;
223
+ displayName?: string;
224
+ connectedAt?: string;
328
225
  }[];
329
- }): Promise<{
330
- urls: SyncPresignedUrl[];
331
- }>;
332
- syncConfirmUpload(args: {
333
- filePath: string;
334
- hash: string;
335
- size: number;
336
- storageClass?: "STANDARD" | "GLACIER_IR";
337
- }): Promise<SyncConfirmedUpload>;
338
- syncReconstruct(args: {
339
- mode: "full" | "active" | "memory";
340
- }): Promise<SyncReconstructBundle>;
341
- syncGetStats(): Promise<SyncAgentStats>;
342
- syncListFiles(args?: {
343
- prefix?: string;
344
- }): Promise<{
345
- files: SyncFileEntry[];
346
- }>;
347
- syncListSessions(): Promise<{
348
- sessions: SyncSessionEntry[];
349
226
  }>;
350
- syncGetSession(sessionId: string): Promise<SyncSessionContent>;
351
- syncDeleteFile(filePath: string): Promise<{
352
- removed: boolean;
227
+ disconnectGoogleAccount(email: string): Promise<{
228
+ accounts: {
229
+ email: string;
230
+ displayName?: string;
231
+ connectedAt?: string;
232
+ }[];
353
233
  }>;
354
- sharedListFiles(args: {
355
- scope: "org" | "team" | "project";
356
- scopeId: string;
357
- limit?: number;
358
- cursor?: string;
359
- }): Promise<{
360
- files: SharedFileEntry[];
361
- nextCursor: string | null;
234
+ getGoogleChatCredentials(): Promise<{
235
+ email: string;
236
+ refreshToken: string;
237
+ clientId: string;
238
+ clientSecret: string;
239
+ displayName?: string;
362
240
  }>;
363
- sharedDownloadUrl(args: {
364
- scope: "org" | "team" | "project";
365
- scopeId: string;
366
- filePath: string;
367
- }): Promise<{
368
- downloadUrl: string;
369
- expiresIn: number;
241
+ /**
242
+ * Fetch decrypted credentials for ONE specific connection by its
243
+ * stable connectionId (connection-scoped, vs the provider-scoped
244
+ * `get<Provider>Credentials` helpers). Used by the daemon to resolve
245
+ * a Custom Connection-driven integration's credentials from the
246
+ * exact connection it was installed from — every custom connection
247
+ * shares the `custom` provider id, so provider-scoping is ambiguous.
248
+ *
249
+ * For custom connections `accessToken` is the JSON-encoded secret
250
+ * bundle (the daemon un-bundles it); non-secret fields are on
251
+ * `providerMetadata`. The endpoint enforces that the connection is in
252
+ * the calling agent's effective scope (403 otherwise).
253
+ */
254
+ getConnectionCredentials(connectionId: string): Promise<{
255
+ provider: string;
256
+ connectionId: string;
257
+ accountIdentifier?: string;
258
+ accessToken?: string;
259
+ providerMetadata?: Record<string, unknown>;
260
+ [key: string]: unknown;
370
261
  }>;
371
- }
372
- //# sourceMappingURL=sync.d.ts.map
373
- //#endregion
374
- //#region src/domains/knowledge.d.ts
375
- type KnowledgeScopeType = "org" | "team" | "project";
376
- interface KnowledgeScope {
377
- scopeType: KnowledgeScopeType;
378
- scopeId: string;
379
- name: string;
380
- }
381
- interface KnowledgeSearchHit {
382
- id: string;
383
- text: string;
384
- /** Normalized relevance in (0,1]; higher = closer. */
385
- score: number;
386
- scopeType: KnowledgeScopeType;
387
- scopeId: string;
388
262
  /**
389
- * Provenance of the hit. All live results are `"doc"`; `"fact"` only ever
390
- * appears for legacy vectors indexed before the facts primitive was removed
391
- * (the search index stays tolerant of them). Treat every hit as a doc.
263
+ * @deprecated Returns a single primary credential blob (legacy "pick-the-
264
+ * default-connection" shape). Use `getGithubAccounts()` for the multi-
265
+ * account shape required by Pattern A explicit selector args on every
266
+ * tool. Retained because the `@alfe.ai/github-mcp` proxy is the
267
+ * only consumer that knows about Pattern A; legacy env-interpolation
268
+ * callers will keep hitting `/credentials` until they move to the proxy.
392
269
  */
393
- source: "doc" | "fact";
394
- /** The canonical file under shared/<scope>/ (present on doc hits). */
395
- filePath?: string;
396
- /** Legacy-only: the id of a pre-removal fact vector. */
397
- factId?: string;
398
- }
399
- interface KnowledgeSearchResult {
400
- results: KnowledgeSearchHit[];
401
- /** True when fan-out breadth was capped (more member scopes than the cap). */
402
- truncatedScopes: boolean;
403
- }
404
- interface KnowledgeProfileLink {
405
- label: string;
406
- url: string;
407
- }
408
- interface KnowledgeProfile {
409
- scopeType: KnowledgeScopeType;
410
- scopeId: string;
411
- about: string | null;
412
- description: string | null;
413
- links: KnowledgeProfileLink[];
414
- updatedAt: string | null;
415
- updatedBy: string | null;
416
- }
417
- type ChangeRequestResourceType = "doc" | "profile";
418
- type ChangeRequestOperation = "create" | "update" | "delete";
419
- type ChangeRequestStatus = "open" | "approved" | "rejected" | "withdrawn" | "superseded";
420
- type ChangeRequestActorKind = "human" | "agent";
421
- /** Public projection of a change request (mirrors `PublicChangeRequest` in services/org). */
422
- interface KnowledgeChangeRequest {
423
- changeRequestId: string;
424
- scopeType: KnowledgeScopeType;
425
- scopeId: string;
426
- resourceType: ChangeRequestResourceType;
427
- operation: ChangeRequestOperation;
428
- targetPath: string | null;
429
- baseVersionId: string | null;
430
- proposedContentType: string | null;
431
- status: ChangeRequestStatus;
432
- proposerId: string;
433
- proposerKind: ChangeRequestActorKind;
434
- rationale: string;
435
- reviewerId: string | null;
436
- reviewerKind: ChangeRequestActorKind | null;
437
- reviewedAt: string | null;
438
- reviewNote: string | null;
439
- appliedRef: string | null;
440
- createdAt: string;
441
- updatedAt: string;
442
- }
443
- /** Per-type proposal payload for `proposeScopeChange`. */
444
- interface ProposeScopeChangeInput {
445
- resourceType: ChangeRequestResourceType;
446
- operation: ChangeRequestOperation;
447
- /** Why the change is proposed — shown to the reviewer. */
448
- rationale: string;
449
- /** doc: the path the proposal applies to (e.g. designs/data-center.md). */
450
- targetPath?: string;
451
- /** doc create/update: the staged body to upload (markdown or other text). */
452
- content?: string;
453
- /** doc create/update: content type of the staged body (default text/markdown). */
454
- contentType?: string;
455
- /** profile: the proposed value ({ about, description, links }). */
456
- proposedValue?: unknown;
457
- }
458
- interface KnowledgeDoc {
459
- filePath: string;
460
- fileName: string;
461
- contentType?: string;
462
- size: number;
463
- uploadedBy?: string;
464
- createdAt: string;
465
- updatedAt: string;
466
- }
467
- declare class KnowledgeApi extends ApiBase {
270
+ getGithubCredentials(): Promise<{
271
+ login: string;
272
+ accessToken: string;
273
+ }>;
468
274
  /**
469
- * Semantic search across the agent's member scopes. Fan-out is gated
470
- * server-side by `listScopes` set-inclusion (fail-closed). Pass
471
- * `scopeType` + `scopeId` to narrow to one scope; a non-member scope
472
- * yields empty results (never a cross-scope leak).
275
+ * Pattern A: multi-account credential fetch for GitHub.
276
+ *
277
+ * Returns every agent-scoped GitHub connection. The caller is expected
278
+ * to require a `login` selector on every credential-touching tool and
279
+ * look up the matching account at dispatch time.
280
+ *
281
+ * GitHub OAuth tokens have no expiry (`tokenLifecycle: "no_expiry"`),
282
+ * so there is intentionally no `refreshGithubAccountToken` method — if
283
+ * a token is revoked the user must re-run the OAuth flow.
284
+ *
285
+ * Returned `accounts[i].login` is the GitHub username — the stable
286
+ * cross-session identifier the LLM should pass.
473
287
  */
474
- knowledgeSearch(query: string, opts?: {
475
- limit?: number;
476
- scopeType?: KnowledgeScopeType;
477
- scopeId?: string;
478
- }): Promise<KnowledgeSearchResult>;
479
- /** Enumerate the scopes (org + teams + projects) this agent belongs to. */
480
- listScopes(): Promise<{
481
- scopes: KnowledgeScope[];
288
+ getGithubAccounts(): Promise<{
289
+ accounts: {
290
+ connectionId: string;
291
+ accountIdentifier: string;
292
+ displayName: string | null;
293
+ connectedAt: string;
294
+ accessToken: string;
295
+ login: string;
296
+ scopes: string;
297
+ }[];
482
298
  }>;
483
- /** Read a scope's structured knowledge profile (after membership check). */
484
- getScopeProfile(scopeType: KnowledgeScopeType, scopeId: string): Promise<KnowledgeProfile>;
485
299
  /**
486
- * Open a change request against a scope's knowledge resource. For a doc
487
- * create/update, `services/org` returns a presigned staging PUT; this method
488
- * uploads the proposed `content` to it (echoing the same Content-Type that
489
- * was signed), mirroring `writeScopeDoc`. The staged body is applied to the
490
- * canonical doc — attributed to this agent — only when a reviewer approves.
300
+ * @deprecated Returns a single primary credential blob (legacy "pick-the-
301
+ * default-connection" shape). Use `getXeroAccounts()` for the multi-
302
+ * account shape required by Pattern A explicit selector args on every
303
+ * tool. This method will be removed once all consumers migrate.
491
304
  */
492
- proposeScopeChange(scopeType: KnowledgeScopeType, scopeId: string, input: ProposeScopeChangeInput): Promise<KnowledgeChangeRequest>;
305
+ getXeroCredentials(): Promise<{
306
+ accessToken: string;
307
+ accessTokenExpiresAt: string;
308
+ xeroTenantId: string;
309
+ }>;
493
310
  /**
494
- * List the agent's OWN change requests in a scope (filtered server-side to
495
- * this agent as proposer). Pass `status` to narrow to open / approved / etc.
311
+ * Pattern A: multi-account credential fetch for Xero. Returns every
312
+ * agent-scoped Xero connection. The caller is expected to require a
313
+ * selector arg (e.g. `xeroTenantId`) on every credential-touching tool
314
+ * and look up the matching account by that selector at dispatch time.
315
+ *
316
+ * `xeroTenantId` is the model-facing organisation selector. The separate
317
+ * `accountIdentifier` is the Connect persistence key used for refresh and
318
+ * may be an email; never substitute one for the other.
496
319
  */
497
- listScopeChangeRequests(scopeType: KnowledgeScopeType, scopeId: string, opts?: {
498
- status?: ChangeRequestStatus;
499
- limit?: number;
500
- cursor?: string;
501
- }): Promise<{
502
- changeRequests: KnowledgeChangeRequest[];
503
- nextCursor: string | null;
320
+ getXeroAccounts(): Promise<{
321
+ accounts: {
322
+ connectionId: string;
323
+ accountIdentifier: string;
324
+ displayName: string | null;
325
+ connectedAt: string;
326
+ accessToken: string;
327
+ accessTokenExpiresAt: string;
328
+ xeroTenantId: string;
329
+ }[];
504
330
  }>;
505
- /** List a scope's docs (the org-files corpus; mirrored to shared/<scope>/). */
506
- listScopeDocs(scopeType: KnowledgeScopeType, scopeId: string, opts?: {
507
- limit?: number;
508
- cursor?: string;
509
- }): Promise<{
510
- files: KnowledgeDoc[];
511
- nextCursor: string | null;
331
+ refreshXeroToken(): Promise<{
332
+ accessToken: string;
333
+ expiresAt: string;
512
334
  }>;
513
335
  /**
514
- * Read the full text of a scope doc. Resolves a presigned download URL
515
- * from `services/org`, then fetches the bytes directly from S3 (the one
516
- * legitimate raw fetch in a plugin same pattern as sync).
336
+ * Refresh a specific Xero Connection by its exact `accountIdentifier` from
337
+ * `getXeroAccounts()`. Do not substitute `xeroTenantId`: current Xero OAuth
338
+ * rows may use the account email as their persistence key even when a sole
339
+ * organisation tenant ID is available in provider metadata.
517
340
  */
518
- readScopeDoc(scopeType: KnowledgeScopeType, scopeId: string, filePath: string, opts?: {
519
- maxBytes?: number;
520
- }): Promise<{
521
- filePath: string;
522
- text: string;
341
+ refreshXeroAccountToken(accountIdentifier: string): Promise<{
342
+ accessToken: string;
343
+ accessTokenExpiresAt: string;
344
+ expiresAt: string;
523
345
  }>;
524
346
  /**
525
- * Write (create or overwrite) a scope doc. Two-step presigned upload:
526
- * `services/org` returns a signed URL plus `requiredHeaders` (author /
527
- * authorKind / message as `x-amz-meta-*`) that MUST be sent verbatim on
528
- * the PUT, alongside the same `Content-Type` that was signed. Author and
529
- * authorKind are server-set from the agent token — never trusted here.
347
+ * @deprecated Returns a single primary credential blob (legacy "pick-the-
348
+ * default-connection" shape). Use `getNotionAccounts()` for the multi-
349
+ * account shape required by Pattern A.
530
350
  */
531
- writeScopeDoc(scopeType: KnowledgeScopeType, scopeId: string, filePath: string, content: string, opts?: {
532
- contentType?: string;
533
- message?: string;
534
- }): Promise<{
535
- filePath: string;
351
+ getNotionCredentials(): Promise<{
352
+ accessToken: string;
353
+ workspaceId: string;
354
+ workspaceName: string;
536
355
  }>;
537
- }
538
- //# sourceMappingURL=knowledge.d.ts.map
539
- //#endregion
540
- //#region src/domains/mobile.d.ts
541
- /** Response of GET /mobile/numbers for an agent (services/mobile). */
542
- interface MobileNumberInfo {
543
- phoneNumber: string;
544
- countryCode: string;
545
- monthlyPrice?: number;
546
- status: string;
547
- errorMessage?: string;
548
- }
549
- /** One purchasable number from GET /mobile/numbers/search. */
550
- interface MobileAvailableNumber {
551
- number: string;
552
- friendlyName: string;
553
- locality: string;
554
- region: string;
555
- country: string;
556
- }
557
- /** Approved WhatsApp content template from GET /mobile/whatsapp/templates. */
558
- interface WhatsAppTemplate {
559
- contentSid: string;
560
- name: string;
561
- language: string;
562
- body: string;
563
- variables: Record<string, string>;
564
- category?: string;
565
- }
566
- declare class MobileApi extends ApiBase {
567
- getMobileNumber(): Promise<MobileNumberInfo>;
568
- searchMobileNumbers(args?: {
569
- country?: string;
570
- query?: string;
571
- }): Promise<{
572
- numbers: MobileAvailableNumber[];
573
- monthlyPrice: number;
356
+ /**
357
+ * Pattern A: multi-account credential fetch for Notion. Returns every
358
+ * agent-scoped Notion connection. The caller is expected to require a
359
+ * selector arg (e.g. `workspaceId`) on every credential-touching tool.
360
+ *
361
+ * Returned `accounts[i].accountIdentifier` is the Notion workspaceId.
362
+ */
363
+ getNotionAccounts(): Promise<{
364
+ accounts: {
365
+ connectionId: string;
366
+ accountIdentifier: string;
367
+ displayName: string | null;
368
+ connectedAt: string;
369
+ accessToken: string;
370
+ workspaceId: string;
371
+ workspaceName: string;
372
+ }[];
574
373
  }>;
575
- assignMobileNumber(args: {
576
- phoneNumber: string;
577
- countryCode: string;
578
- }): Promise<{
579
- phoneNumber: string;
580
- countryCode: string;
581
- status: "pending";
582
- }>;
583
- releaseMobileNumber(): Promise<{
584
- released: true;
585
- }>;
586
- sendSms(args: {
587
- to: string;
588
- body: string;
589
- }): Promise<{
590
- sent: true;
591
- sid: string;
592
- }>;
593
- startOutboundCall(args: {
594
- to: string;
595
- }): Promise<{
596
- callSid: string;
597
- status: string;
374
+ /**
375
+ * @deprecated Returns a single primary Atlassian Connection's credentials
376
+ * (one OAuth user, one cloudId) — the legacy "pick-the-default-connection"
377
+ * shape. Atlassian is multi-site by nature (each OAuth user may have
378
+ * access to multiple Cloud sites), so Pattern A plugins MUST use
379
+ * `getAtlassianAccounts()` to discover the full set and dispatch via
380
+ * the `cloudId` selector arg.
381
+ */
382
+ getAtlassianCredentials(): Promise<{
383
+ accessToken: string;
384
+ refreshToken: string;
385
+ accessTokenExpiresAt: string;
386
+ cloudId: string;
387
+ siteName: string;
388
+ siteUrl: string;
389
+ email: string;
390
+ enabledProducts: string[];
391
+ clientId: string;
392
+ clientSecret: string;
598
393
  }>;
599
- getWhatsAppSession(to: string): Promise<{
600
- active: boolean;
601
- expiresAt?: string;
394
+ refreshAtlassianToken(): Promise<{
395
+ accessToken: string;
396
+ expiresAt: string;
602
397
  }>;
603
- sendWhatsAppMessage(args: {
604
- to: string;
605
- body: string;
606
- }): Promise<{
607
- sent: true;
608
- sid: string;
398
+ /**
399
+ * Pattern A: multi-account / multi-site credential fetch for Atlassian.
400
+ *
401
+ * Returns every agent-scoped Atlassian Connection. Each Connection is
402
+ * one OAuth user with a single access token and N accessible Cloud
403
+ * sites (`availableSites`). The caller is expected to:
404
+ *
405
+ * 1. Flatten (connection × cloudId) into one MCP child per site.
406
+ * 2. Require a `cloudId` selector on every credential-touching tool.
407
+ * 3. Use the access token bound to the Connection that owns the
408
+ * requested `cloudId` (Atlassian shares one access token across
409
+ * all sites accessible to the OAuth user).
410
+ *
411
+ * Per-account token refresh uses `refreshAtlassianAccountToken(email)`
412
+ * — refreshing one Connection rotates its single access token, which
413
+ * then applies to every cloudId for that Connection.
414
+ *
415
+ * Returned `accounts[i].accountIdentifier` is the OAuth user's email
416
+ * — the stable cross-session identifier for refresh purposes. The LLM
417
+ * never sees this directly: it picks a site via the `cloudId` arg
418
+ * instead.
419
+ */
420
+ getAtlassianAccounts(): Promise<{
421
+ accounts: {
422
+ connectionId: string;
423
+ accountIdentifier: string;
424
+ displayName: string | null;
425
+ connectedAt: string;
426
+ accessToken: string;
427
+ accessTokenExpiresAt: string;
428
+ clientId: string;
429
+ clientSecret: string;
430
+ cloudId: string;
431
+ siteName: string;
432
+ siteUrl: string;
433
+ availableSites: {
434
+ id: string;
435
+ url: string;
436
+ name: string;
437
+ scopes?: string[];
438
+ avatarUrl?: string;
439
+ }[];
440
+ }[];
609
441
  }>;
610
- sendWhatsAppTemplate(args: {
611
- to: string;
612
- contentSid: string;
613
- contentVariables: Record<string, string>;
614
- bodyPreview?: string;
615
- }): Promise<{
616
- sent: true;
617
- sid: string;
442
+ /**
443
+ * Pattern A: refresh a specific Atlassian Connection by `accountIdentifier`
444
+ * (the OAuth user's email).
445
+ *
446
+ * Atlassian rotates refresh tokens (`rotatesRefreshToken: true`); the
447
+ * server-side per-account refresh endpoint handles rotation and
448
+ * persistence. Refreshing one Connection updates its single access
449
+ * token, which applies to every accessible Cloud site (cloudId) for
450
+ * that OAuth user.
451
+ *
452
+ * Returns the new access token + expiry. The proxy is responsible for
453
+ * fanning the new token out to every child server it spawned for
454
+ * cloudIds owned by this Connection.
455
+ */
456
+ refreshAtlassianAccountToken(accountIdentifier: string): Promise<{
457
+ accessToken: string;
458
+ accessTokenExpiresAt: string;
459
+ expiresAt: string;
618
460
  }>;
619
- listWhatsAppTemplates(): Promise<{
620
- templates: WhatsAppTemplate[];
461
+ /**
462
+ * @deprecated Returns a single primary credential blob (legacy "pick-the-
463
+ * default-connection" shape). Use `getMYOBAccounts()` for the multi-
464
+ * account shape required by Pattern A.
465
+ */
466
+ getMYOBCredentials(): Promise<{
467
+ accessToken: string;
468
+ accessTokenExpiresAt: string;
469
+ myobBusinessId: string;
470
+ clientId: string;
621
471
  }>;
622
- }
623
- //# sourceMappingURL=mobile.d.ts.map
624
- //#endregion
625
- //#region src/domains/remote.d.ts
626
- interface RemoteSessionInfo {
627
- sessionId: string;
628
- agentId: string;
629
- surface: "browser" | "terminal";
630
- status: "agent_driving" | "awaiting_human" | "human_in_control" | "resuming" | "completed" | "expired" | "failed";
631
- url?: string;
632
- instructions?: string;
633
- requestedAt?: string;
634
- }
635
- declare class RemoteApi extends ApiBase {
636
- requestBrowserTakeover(args: {
637
- instructions: string;
638
- url?: string;
639
- conversationId?: string;
640
- }): Promise<{
641
- sessionId: string;
642
- status: string;
472
+ /**
473
+ * Pattern A: multi-account credential fetch for MYOB. Returns every
474
+ * agent-scoped MYOB connection. The caller is expected to require a
475
+ * selector arg (e.g. `myobBusinessId` / `accountIdentifier`) on every
476
+ * credential-touching tool.
477
+ *
478
+ * Returned `accounts[i].accountIdentifier` is the MYOB businessId.
479
+ */
480
+ getMYOBAccounts(): Promise<{
481
+ accounts: {
482
+ connectionId: string;
483
+ accountIdentifier: string;
484
+ displayName: string | null;
485
+ connectedAt: string;
486
+ accessToken: string;
487
+ accessTokenExpiresAt: string;
488
+ myobBusinessId: string;
489
+ clientId: string;
490
+ }[];
643
491
  }>;
644
- getRemoteSession(sessionId: string): Promise<RemoteSessionInfo>;
645
- completeRemoteSession(sessionId: string): Promise<{
646
- ok: boolean;
492
+ refreshMYOBToken(): Promise<{
493
+ accessToken: string;
494
+ expiresAt: string;
647
495
  }>;
648
- }
649
- //# sourceMappingURL=remote.d.ts.map
650
- //#endregion
651
- //#region src/domains/self.d.ts
652
- /** Voice settings — core agent config. Mirrors `VoiceConfig` in `@alfe/types`. */
653
- interface AgentVoiceConfig {
654
- /** ElevenLabs voice ID; platform default when unset. */
655
- voiceId?: string;
656
- ttsModel?: string;
657
- enabled?: boolean;
658
- }
659
- /**
660
- * The agent's own public identity, as returned by `updateSelf`, `generateAvatar`,
661
- * `presignAvatar`'s finalize (`finalizeAvatar`). This is the public agent
662
- * projection; only the identity-relevant fields are typed here — the response
663
- * carries the full public agent record.
664
- */
665
- interface AgentSelf {
666
- agentId: string;
667
- tenantId: string;
668
- name: string;
669
- avatarUrl?: string;
670
- voiceConfig?: AgentVoiceConfig;
671
- status: string;
672
- }
673
- /** Result of `presignAvatar` — the agent PUTs bytes to `uploadUrl`, then finalizes with `s3Key`. */
674
- interface AgentAvatarPresign {
675
- /** Presigned PUT URL to upload the image bytes to. */
676
- uploadUrl: string;
677
- /** Object key — echoed back to `finalizeAvatar`. */
678
- s3Key: string;
679
- /** Stable public URL the avatar will be served from once finalized. */
680
- publicUrl: string;
681
- /** ISO expiry of the presigned PUT URL. */
682
- expiresAt: string;
683
- }
684
- /** A voice in the platform catalogue (ElevenLabs), from `listVoices`. */
685
- interface AgentVoice {
686
- id: string;
687
- name: string;
688
- previewUrl: string;
689
- description: string;
690
- labels: Record<string, string>;
691
- category: string;
692
- }
693
- declare class SelfApi extends ApiBase {
694
- /** Update the agent's own name and/or voice config. Returns the updated agent. */
695
- updateSelf(update: {
696
- name?: string;
697
- voiceConfig?: AgentVoiceConfig;
698
- }): Promise<AgentSelf>;
699
496
  /**
700
- * Generate the agent's own avatar from a text prompt. The image is generated,
701
- * stored, and set on the agent server-side; returns the updated agent.
497
+ * Pattern A: refresh one MYOB Connection by its stable
498
+ * `accountIdentifier` (the MYOB business id returned by
499
+ * `getMYOBAccounts()`).
702
500
  *
703
- * ASYNC (same reason as `generateImage`): avatar gen runs `gpt-image-1`
704
- * (30–60s) which exceeds the API Gateway 30s ceiling, so this enqueues a job
705
- * (`POST /agent/avatar/generate` `jobId`) then polls (`GET /agent/avatar/{jobId}`)
706
- * until the avatar is set. Signature unchanged — the plugin is unaffected.
501
+ * MYOB refresh tokens belong to individual Connection rows. A
502
+ * multi-business client must use this method instead of refreshing the
503
+ * primary Connection and copying that access token into every cached
504
+ * business client.
707
505
  */
708
- generateAvatar(args: {
709
- prompt: string;
710
- }): Promise<AgentSelf>;
506
+ refreshMYOBAccountToken(accountIdentifier: string): Promise<{
507
+ accessToken: string;
508
+ accessTokenExpiresAt: string;
509
+ expiresAt: string;
510
+ }>;
711
511
  /**
712
- * Get a presigned PUT URL to upload a new avatar image. Upload the bytes to
713
- * `uploadUrl`, then call `finalizeAvatar(s3Key)` to set it on the agent.
512
+ * @deprecated Returns a single primary credential blob. Use
513
+ * `getSalesforceAccounts()` for the multi-account shape required by
514
+ * Pattern A.
714
515
  */
715
- presignAvatar(args: {
716
- mimeType: string;
717
- size: number;
718
- }): Promise<AgentAvatarPresign>;
516
+ getSalesforceCredentials(): Promise<{
517
+ accessToken: string;
518
+ accessTokenExpiresAt: string;
519
+ instanceUrl: string;
520
+ orgId: string;
521
+ }>;
719
522
  /**
720
- * Finalize an avatar upload validates ownership + size, then sets the
721
- * agent's `avatarUrl` server-side. Returns the updated agent.
523
+ * Pattern A: multi-account credential fetch for Salesforce. Returns every
524
+ * agent-scoped Salesforce connection. One OAuth grant maps to one org, so
525
+ * `accounts[i].accountIdentifier` (and `orgId`) is the Salesforce org id —
526
+ * the selector every credential-touching tool requires.
722
527
  */
723
- finalizeAvatar(s3Key: string): Promise<AgentSelf>;
724
- /** List the platform voice catalogue (ElevenLabs) so the agent can pick its own voice. */
725
- listVoices(): Promise<{
726
- voices: AgentVoice[];
528
+ getSalesforceAccounts(): Promise<{
529
+ accounts: {
530
+ connectionId: string;
531
+ accountIdentifier: string;
532
+ displayName: string | null;
533
+ connectedAt: string;
534
+ accessToken: string;
535
+ accessTokenExpiresAt: string;
536
+ instanceUrl: string;
537
+ orgId: string;
538
+ }[];
727
539
  }>;
728
- }
729
- //# sourceMappingURL=self.d.ts.map
730
- //#endregion
731
- //#region src/domains/voice.d.ts
732
- /** The ElevenLabs models with a pricing row — the TTS endpoint rejects any other value. */
733
- type VoiceTtsModel = "eleven_turbo_v2_5" | "eleven_multilingual_v2";
734
- interface VoiceTtsArgs {
735
- /** Text to synthesize (1–5000 chars — the endpoint enforces this). */
736
- text: string;
737
- /** ElevenLabs voice id; platform default when unset. */
738
- voiceId?: string;
739
- /** TTS model; `eleven_turbo_v2_5` (lower latency) when unset. */
740
- model?: VoiceTtsModel;
741
- }
742
- /** Raw synthesized audio plus its PCM framing (from the response headers). */
743
- interface VoiceTtsResult {
744
- /** Raw little-endian PCM samples — no container. Wrap in WAV to make a playable file. */
745
- audio: Buffer;
746
- /** Samples per second (e.g. 24000). */
747
- sampleRate: number;
748
- /** Channel count (mono = 1). */
749
- channels: number;
750
- /** Bits per sample (e.g. 16). */
751
- bitDepth: number;
752
- }
753
- interface VoiceSttArgs {
754
- /** Raw linear16 (16-bit little-endian) mono PCM samples — no WAV/container header. */
755
- audio: Uint8Array;
756
- /** Sample rate of `audio` in Hz (8000–48000). */
757
- sampleRate: number;
758
- }
759
- interface VoiceSttResult {
760
- text: string;
761
- /** Deepgram confidence in (0,1]. */
762
- confidence: number;
763
- }
764
- declare class VoiceApi extends ApiBase {
765
540
  /**
766
- * Text-to-speech. Returns raw PCM audio bytes plus their framing — the
767
- * voice service defaults to 24 kHz / mono / 16-bit. Wrap in a WAV container
768
- * to produce a playable file. Metered per character against the tenant
769
- * credit pool server-side; TTS completes regardless of metering outcome.
541
+ * Refresh the access token for a specific Salesforce org. Salesforce
542
+ * tokens aren't interchangeable across orgs, so the connection is targeted
543
+ * by `accountIdentifier` (the org id) mirrors `refreshXeroAccountToken`.
770
544
  */
771
- tts(args: VoiceTtsArgs): Promise<VoiceTtsResult>;
545
+ refreshSalesforceAccountToken(orgId: string): Promise<{
546
+ accessToken: string;
547
+ accessTokenExpiresAt: string;
548
+ expiresAt: string;
549
+ }>;
772
550
  /**
773
- * Speech-to-text. Accepts raw linear16 (16-bit LE) mono PCM NOT a WAV or
774
- * other container (the endpoint transcribes with a fixed linear16 encoding,
775
- * so a container header would be transcribed as noise). Strip any WAV header
776
- * and pass `sampleRate` from it before calling. Metered by transcribed
777
- * duration against the tenant credit pool server-side.
551
+ * Pattern A: multi-account credential fetch for Microsoft 365.
552
+ *
553
+ * Returns every agent-scoped Microsoft connection. The caller is expected
554
+ * to require an `email` selector on every credential-touching tool and
555
+ * look up the matching account at dispatch time.
556
+ *
557
+ * Returned `accounts[i].accountIdentifier` is the user's primary email
558
+ * (or the tid claim as fallback) — the stable cross-session identifier
559
+ * the LLM should pass.
560
+ *
561
+ * Per-account token refresh is exposed via `refreshMicrosoftAccountToken`,
562
+ * NOT `refreshXeroAccountToken` — Microsoft refresh tokens are not
563
+ * interchangeable across (tenant, user) pairs.
778
564
  */
779
- stt(args: VoiceSttArgs): Promise<VoiceSttResult>;
780
- }
781
- //# sourceMappingURL=voice.d.ts.map
782
- //#endregion
783
- //#region src/domains/identity.d.ts
784
- type IdentityStatus = "anonymous" | "partial" | "identified" | "verified";
785
- interface IdentityDirectoryEntry {
786
- identityId: string;
787
- status: IdentityStatus;
788
- displayName: string;
789
- name?: string;
790
- avatarUrl?: string;
791
- lastSeenAt: string;
792
- lastSeenProvider?: string;
793
- messageable: boolean;
794
- }
795
- declare class IdentityApi extends ApiBase {
565
+ getMicrosoftAccounts(): Promise<{
566
+ accounts: {
567
+ connectionId: string;
568
+ accountIdentifier: string;
569
+ displayName: string | null;
570
+ connectedAt: string;
571
+ accessToken: string;
572
+ accessTokenExpiresAt: string;
573
+ email: string;
574
+ microsoftTenantId: string;
575
+ workspaceDomain: string;
576
+ }[];
577
+ }>;
796
578
  /**
797
- * Returns the calling agent's own identity context `{ agentId, tenantId }`
798
- * decoded server-side from the agent API token. Used by the
799
- * `@alfe.ai/openclaw-identity` plugin to bootstrap context when the
800
- * OpenClaw daemon doesn't plumb `ctx.agentId` through to plugin hooks.
801
- * Plugins should cache this for the daemon's lifetime (single-agent-per-
802
- * process invariant). One HTTP round-trip per process activate; not for
803
- * per-call use.
579
+ * Pattern A: refresh a specific Microsoft 365 connection by its
580
+ * `accountIdentifier`. For Microsoft, `accountIdentifier` is the user's
581
+ * email when the Graph profile fetch succeeded at connect time, and the
582
+ * Azure tenant id (`tid` claim) as fallback. Callers should pass the
583
+ * value returned by `getMicrosoftAccounts()` rather than synthesising
584
+ * an email locally.
585
+ *
586
+ * Microsoft refresh tokens are bound to a specific (tenant, user) pair —
587
+ * they are NOT interchangeable across accounts, so per-account refresh
588
+ * is mandatory. The generic /accounts/{accountIdentifier}/refresh
589
+ * endpoint walks the agent's full visible scope chain to find a matching
590
+ * connection (works for inherited team/project Microsoft connections).
804
591
  */
805
- whoami(): Promise<{
806
- agentId: string;
807
- tenantId: string;
808
- }>;
809
- resolveIdentity(args: {
810
- provider: string;
811
- platformId: string;
812
- kind?: "user" | "agent" | "service" | "bot" | "workspace";
813
- displayName?: string;
814
- }): Promise<{
815
- identityId: string | null;
816
- status: string;
817
- created?: boolean;
818
- reason?: string;
819
- /**
820
- * Flattened auriclabs permission strings for the resolved identity
821
- * (scope-prefixed where applicable). Empty array on miss / org service
822
- * outage — the runtime gate fails closed in that case.
823
- */
824
- permissions: string[];
825
- }>;
826
- searchIdentities(args?: {
827
- q?: string;
828
- status?: string;
829
- limit?: number;
830
- }): Promise<{
831
- identities: unknown[];
832
- }>;
833
- listIdentities(args?: {
834
- status?: IdentityStatus;
835
- limit?: number;
836
- cursor?: string;
837
- }): Promise<{
838
- identities: IdentityDirectoryEntry[];
839
- cursor: string | null;
840
- }>;
841
- getIdentityContext(identityId: string): Promise<{
842
- context: unknown;
843
- }>;
844
- mergeIdentities(survivorId: string, args: {
845
- mergedId: string;
846
- }): Promise<{
847
- ok: boolean;
848
- error?: string;
849
- }>;
850
- unmergeIdentity(identityId: string): Promise<{
851
- ok: boolean;
852
- error?: string;
853
- }>;
854
- addIdentityNote(identityId: string, args: {
855
- content: string;
856
- category?: string;
857
- }): Promise<{
858
- noteId: string | null;
592
+ refreshMicrosoftAccountToken(accountIdentifier: string): Promise<{
593
+ accessToken: string;
594
+ accessTokenExpiresAt: string;
595
+ expiresAt: string;
859
596
  }>;
860
- tagIdentity(identityId: string, args: {
861
- tag: string;
862
- action: "add" | "remove";
863
- }): Promise<{
864
- ok: boolean;
597
+ /**
598
+ * Disconnects one connected Microsoft 365 account for the agent, by its
599
+ * `accountIdentifier`. Hits the generic per-account disconnect route
600
+ * (`DELETE /agent/connect/microsoft/accounts/{accountIdentifier}`), which
601
+ * resolves across the agent's full effective scope chain and deletes the
602
+ * matching Connection row. Returns the remaining accounts.
603
+ *
604
+ * IMPORTANT: pass the `accountIdentifier` from `getMicrosoftAccounts()`, NOT
605
+ * a synthesised email. For Microsoft, `accountIdentifier` is the user's email
606
+ * only when the Graph profile fetch succeeded at connect time; it falls back
607
+ * to the Azure tenant id (`tid` claim) otherwise. The backend matches on
608
+ * `accountIdentifier` exactly, so passing an email would 404 on those
609
+ * fallback-identifier accounts. (This is why the param is not named `email`,
610
+ * unlike `disconnectGoogleAccount` where the identifier is always the email.)
611
+ */
612
+ disconnectMicrosoftAccount(accountIdentifier: string): Promise<{
613
+ accounts: {
614
+ accountIdentifier: string;
615
+ displayName?: string;
616
+ connectedAt?: string;
617
+ }[];
865
618
  }>;
866
- getIdentityChangelog(identityId: string, args?: {
867
- limit?: number;
868
- cursor?: string;
869
- }): Promise<{
870
- entries: unknown[];
871
- cursor: string | null;
619
+ /**
620
+ * Resolve the primary cTrader Connection's credentials for the calling
621
+ * agent. Unlike most providers, the cTrader Open API needs app-level auth
622
+ * (`clientId` + `clientSecret`) AND account auth (`accessToken` +
623
+ * `accountId`) on the socket, so `@alfe.ai/ctrader-mcp` self-fetches the
624
+ * full set here at startup (the atlassian/google pattern). `clientId` /
625
+ * `clientSecret` are the SST-sourced global app credentials the connect
626
+ * endpoint injects — they are never persisted on the connection. `host` is
627
+ * the resolved TLS endpoint (`live.ctraderapi.com` / `demo.ctraderapi.com`)
628
+ * derived from the selected account's live/demo flag.
629
+ */
630
+ getCTraderCredentials(): Promise<{
631
+ accessToken: string;
632
+ refreshToken: string;
633
+ accountId: string;
634
+ host: string;
635
+ clientId: string;
636
+ clientSecret: string;
872
637
  }>;
873
- rollbackIdentity(identityId: string, args: {
874
- targetVersion: number;
875
- }): Promise<{
876
- ok: boolean;
877
- entry?: unknown;
638
+ /**
639
+ * Pattern A: multi-account credential fetch for cTrader.
640
+ *
641
+ * Unlike atlassian/salesforce (one Connection row per account/site), a
642
+ * cTrader is MULTI-grant per agent: an agent may connect several distinct
643
+ * cTrader logins, each its own Connection row keyed on `accountIdentifier =
644
+ * ctid:<userId>` (Phase 1). This aggregates the *trading accounts* across
645
+ * ALL of those Connection rows — each row contributes its `availableAccounts`
646
+ * flattened, and every account carries ITS OWN grant's `accessToken` (the
647
+ * token that authenticates that account against the cTrader Open API). One
648
+ * OAuth grant still covers all accounts under that single login on one shared
649
+ * token; only the `ctidTraderAccountId` and the protobuf socket `host` (live
650
+ * vs demo) differ within a grant. Across grants the tokens differ, so the
651
+ * token is now PER-ACCOUNT rather than hoisted to the top level.
652
+ *
653
+ * `host` per account is derived from the account's `isLive` flag
654
+ * (`live.ctraderapi.com` / `demo.ctraderapi.com`) — the same mapping the
655
+ * connect provider applies server-side when an account is auto-selected.
656
+ *
657
+ * `clientId` / `clientSecret` are the SST-sourced GLOBAL app credentials the
658
+ * connect endpoint injects — identical across every Connection row (one
659
+ * cTrader app), never persisted on a connection. We take them from the first
660
+ * row that carries them.
661
+ *
662
+ * Accounts are deduped on `ctidTraderAccountId` first-wins: Spotware ids are
663
+ * globally unique across logins, so a duplicate can only appear if the same
664
+ * account somehow surfaced under two grants — first-wins keeps it
665
+ * deterministic.
666
+ *
667
+ * `accounts` may be empty (no cTrader Connection at all), in which case we
668
+ * return empty creds rather than throwing.
669
+ */
670
+ getCTraderAccounts(): Promise<{
671
+ accounts: {
672
+ ctidTraderAccountId: string;
673
+ host: string;
674
+ isLive: boolean;
675
+ brokerName?: string;
676
+ accountNumber?: string;
677
+ accessToken: string;
678
+ /**
679
+ * The stable per-grant Connection key (`ctid:<userId>`) this account
680
+ * belongs to. Every trading account under one cTrader login shares one
681
+ * grant (one OAuth token), so this is the identifier the MCP server
682
+ * passes to `refreshCTraderAccount()` to rotate the token for the whole
683
+ * grant on a `CH_ACCESS_TOKEN_INVALID` expiry. Empty string when the
684
+ * server did not supply one (legacy rows) — such an account can still
685
+ * trade with its current token but cannot self-refresh.
686
+ */
687
+ accountIdentifier: string;
688
+ }[];
689
+ clientId: string;
690
+ clientSecret: string;
878
691
  }>;
879
- requestIdentityVerification(args: {
880
- claimedIdentityId: string;
881
- requestingIdentityId: string;
882
- requestingProvider: string;
883
- requestingPlatformId: string;
884
- preferredChannel?: "mobile" | "email";
885
- /**
886
- * Phase 2: agent-supplied contact endpoint. When provided, the top-level
887
- * `preferredChannel` is ignored the contact's channel wins.
888
- */
889
- contact?: {
890
- channel: "email" | "mobile";
891
- value: string;
892
- };
893
- }): Promise<{
894
- verificationId: string;
895
- channel: string;
896
- deliveredTo: string;
692
+ /**
693
+ * Pattern A: refresh a specific cTrader grant by its stable
694
+ * `accountIdentifier` (`ctid:<userId>` from `getCTraderAccounts()`).
695
+ *
696
+ * cTrader access tokens live ~30 days; the `getCTraderAccounts()` /
697
+ * credentials reads serve the STORED token without refreshing, so refresh is
698
+ * the consumer's job. `@alfe.ai/ctrader-mcp` calls this when the cTrader Open
699
+ * API rejects an account-auth with `CH_ACCESS_TOKEN_INVALID`, then re-runs
700
+ * the socket handshake with the returned `accessToken`.
701
+ *
702
+ * Refreshing one grant rotates the single OAuth token that covers EVERY
703
+ * trading account under that login. cTrader's refresh token itself does not
704
+ * expire but may rotate on refresh (`rotatesRefreshToken: true`); connect
705
+ * persists the rotated refresh token server-side, so the caller only needs
706
+ * the new `accessToken`. Mirrors `refreshXeroAccountToken`.
707
+ */
708
+ refreshCTraderAccount(accountIdentifier: string): Promise<{
709
+ accessToken: string;
710
+ accessTokenExpiresAt: string;
897
711
  expiresAt: string;
898
- availableChannels: {
899
- channel: string;
900
- deliveredTo: string;
901
- }[];
902
- } | {
903
- error: string;
904
712
  }>;
905
- confirmIdentityVerification(args: {
906
- claimedIdentityId: string;
907
- verificationId: string;
908
- phrase: string;
909
- }): Promise<{
910
- verified: boolean;
911
- identityId?: string;
912
- /** Phase 2: how the confirm resolved — Scenario A vs B. */
913
- action?: "merged" | "contact_verified" | "already_confirmed";
914
- error?: string;
713
+ /**
714
+ * @deprecated Returns a single primary credential blob. Use
715
+ * `getShopifyAccounts()` for the multi-account shape required by Pattern A
716
+ * (`@alfe.ai/shopify-mcp` keys per-shop on the myshopify domain).
717
+ */
718
+ getShopifyCredentials(): Promise<{
719
+ accessToken: string;
720
+ shopDomain: string;
721
+ shopGid: string;
722
+ shopName: string;
723
+ apiVersion: string;
915
724
  }>;
916
725
  /**
917
- * Update display-shape fields on an Identity. Body excludes `email` /
918
- * `phone` / `title` / `company` / `metadata` per Section D4 contacts go
919
- * via the verify flow, title/company live on OrgMembership, metadata is
920
- * not agent-writable.
726
+ * Pattern A: multi-account credential fetch for Shopify. Returns every
727
+ * agent-scoped Shopify Connection. One OAuth grant maps to one store, so the
728
+ * stable per-call selector is the store's myshopify domain (`shopDomain`),
729
+ * NOT `accountIdentifier` — the connect provider keys `accountIdentifier` on
730
+ * the immutable shop GID (falling back to the domain), so `shopDomain` is the
731
+ * value the LLM passes and the plugin routes on.
732
+ *
733
+ * Each entry is shaped by the connect provider's `buildCredentialsResponse`:
734
+ * `{ accessToken, shopDomain, shopGid, shopName, apiVersion }` — offline
735
+ * Shopify tokens never expire, so there is NO token / expiry field and no
736
+ * refresh method (unlike Salesforce). The GraphQL Admin API authenticates
737
+ * purely on `X-Shopify-Access-Token`; no client credentials are on the wire.
921
738
  */
922
- updateIdentity(identityId: string, args: {
923
- name?: string;
924
- avatarUrl?: string;
925
- timezone?: string;
926
- locale?: string;
927
- }): Promise<{
928
- ok: boolean;
739
+ getShopifyAccounts(): Promise<{
740
+ accounts: {
741
+ connectionId: string;
742
+ accountIdentifier: string;
743
+ displayName: string | null;
744
+ connectedAt: string;
745
+ accessToken: string;
746
+ shopDomain: string;
747
+ shopGid: string;
748
+ shopName: string;
749
+ apiVersion: string;
750
+ }[];
929
751
  }>;
930
752
  /**
931
- * Phase 2 (Section H): server-side verification of a Google Chat sender via
932
- * the agent's existing Google OAuth credentials. Returns the resolved
933
- * identity (created or matched via Scenario-B email enrichment).
753
+ * Pattern A: provider-parameterized multi-account credential fetch for the
754
+ * social connectors (Bluesky, and the approval-gated backlog: X, Meta,
755
+ * Threads, LinkedIn, Pinterest, TikTok, Reddit, YouTube).
756
+ *
757
+ * Unlike the bespoke `getGithubAccounts()` / `getXeroAccounts()` shapes,
758
+ * this returns a UNIFORM normalized account shape so `@alfe.ai/social-mcp`'s
759
+ * shared driver can require a single `account` selector on every
760
+ * credential-touching tool regardless of platform. The backend
761
+ * `api-agents/{provider}/accounts` route is already provider-generic; this
762
+ * is the client-side normalization the plan (`do-we-need-any-moonlit-toucan`
763
+ * Phase 0, step 5) calls for.
764
+ *
765
+ * `accountIdentifier` is the stable per-account selector the LLM should
766
+ * pass back (for Bluesky: the account DID). `accessToken` carries whatever
767
+ * the provider's `buildCredentialsResponse` bundles (for Bluesky: the JSON
768
+ * session bundle — the driver parses the `accessJwt` out of it, or reads the
769
+ * top-level `accessJwt` from `providerMetadata`-adjacent fields). Everything
770
+ * else the driver needs for routing (handle, pdsHost, did, …) is on
771
+ * `providerMetadata`.
772
+ *
773
+ * Token refresh is delegated to connect (never done in-plugin) via the
774
+ * per-account route `POST /agent/connect/{provider}/accounts/{accountIdentifier}/refresh`
775
+ * — call `refreshSocialAccount(provider, accountIdentifier)`. (The non-account
776
+ * `POST /agent/connect/{provider}/refresh` route refreshes the provider's
777
+ * PRIMARY connection, which is wrong under multi-account Pattern A.)
934
778
  */
935
- resolveGoogleChatSender(args: {
936
- senderUserId: string;
937
- spaceId?: string;
938
- }): Promise<{
939
- identityId: string | null;
940
- status: string;
779
+ getSocialAccounts(provider: string): Promise<{
780
+ provider: string;
781
+ accounts: {
782
+ connectionId: string;
783
+ accountIdentifier: string;
784
+ displayName: string | null;
785
+ accessToken: string;
786
+ providerMetadata: Record<string, unknown>;
787
+ connectedAt: string;
788
+ }[];
789
+ }>;
790
+ /**
791
+ * Pattern A: refresh a specific social Connection by its stable
792
+ * `accountIdentifier` (for Bluesky: the account DID) via the
793
+ * provider-generic per-account refresh route. The counterpart to
794
+ * `getSocialAccounts(provider)`; `@alfe.ai/social-mcp` calls this on a
795
+ * 401/ExpiredToken from the platform PDS/API, then re-fetches accounts to
796
+ * pick up the rotated bundle.
797
+ *
798
+ * Refresh itself is ALWAYS delegated to connect — the plugin never calls
799
+ * the platform's own refresh XRPC (e.g. `com.atproto.server.refreshSession`)
800
+ * because connect owns the encrypted refresh token + rotation persistence
801
+ * (Bluesky rotates the refreshJwt; a missed rotation kills the connection
802
+ * after one refresh). The returned `accessToken` is whatever the provider's
803
+ * `refreshToken` hook re-bundled (for Bluesky: the JSON session bundle with
804
+ * the fresh `accessJwt`) — callers typically ignore it and re-fetch via
805
+ * `getSocialAccounts` for a consistent shape.
806
+ */
807
+ refreshSocialAccount(provider: string, accountIdentifier: string): Promise<{
808
+ accountIdentifier: string;
809
+ accessToken: string;
810
+ accessTokenExpiresAt: string;
811
+ expiresAt: string;
941
812
  }>;
942
813
  }
943
- //# sourceMappingURL=identity.d.ts.map
814
+ //# sourceMappingURL=connect-credentials.d.ts.map
944
815
  //#endregion
945
- //#region src/domains/search.d.ts
816
+ //#region src/domains/integrations.d.ts
946
817
  /**
947
- * The broad-news providers behind the metered `services/news` Lambda. The
948
- * server validates this with a zod enum; a value outside the union is an
949
- * unpriceable product, so keep the literal union in lockstep with the service.
818
+ * One entry in the agent's EFFECTIVE integration list. Agent-scope install
819
+ * rows keep their full public row shape (config included, `scope: "agent"`);
820
+ * connection-/channel-/custom-driven activations and inherited
821
+ * org/team/project installs have no agent-scope row and appear as the
822
+ * narrower projection. Discriminate on `config`: only the agent-scope row
823
+ * arm carries it (`source` alone is NOT a discriminator — inherited explicit
824
+ * rows land in the narrow arm with `source: "explicit"` too).
950
825
  */
951
- type NewsProvider = "apitube" | "newsdata";
952
- /** One normalized article. `sentiment` is provider-shaped (APITube supplies it). */
953
- interface NewsArticle {
954
- title: string;
955
- url: string;
956
- source: string;
957
- publishedAt: string;
958
- snippet: string;
959
- sentiment?: unknown;
960
- }
961
- /** Provider-agnostic result — the server normalizes every adapter to this. */
962
- interface NewsResult {
963
- articles: NewsArticle[];
964
- provider: string;
965
- }
966
- declare class SearchApi extends ApiBase {
967
- searchWeb(params: {
968
- query: string;
969
- count?: number;
970
- offset?: number;
971
- country?: string;
972
- freshness?: string;
973
- }, options?: {
974
- signal?: AbortSignal;
975
- }): Promise<unknown>;
976
- searchImages(params: {
977
- query: string;
978
- count?: number;
979
- }, options?: {
980
- signal?: AbortSignal;
981
- }): Promise<unknown>;
982
- searchNews(params: {
983
- query: string;
984
- count?: number;
985
- offset?: number;
986
- freshness?: string;
987
- }, options?: {
988
- signal?: AbortSignal;
989
- }): Promise<unknown>;
990
- /** Search news across the selected provider's corpus. → POST /agent/news/search */
991
- newsSearch(params: {
992
- query: string;
993
- provider?: NewsProvider;
994
- source?: string;
995
- from?: string;
996
- to?: string;
997
- language?: string;
998
- category?: string;
999
- limit?: number;
1000
- }): Promise<NewsResult>;
1001
- /** Top headlines for the selected provider. → POST /agent/news/headlines */
1002
- newsHeadlines(params?: {
1003
- provider?: NewsProvider;
1004
- category?: string;
1005
- source?: string;
1006
- language?: string;
1007
- limit?: number;
1008
- }): Promise<NewsResult>;
826
+ type AgentIntegrationListEntry = (IntegrationInstall & {
827
+ source: "explicit";
828
+ }) | {
829
+ integrationId: string;
830
+ version: string;
831
+ desiredStatus: IntegrationDesiredStatus;
832
+ actualStatus: IntegrationActualStatus;
833
+ source: IntegrationActivationSource;
834
+ /** Winning row's scope — present only on inherited explicit entries. */
835
+ scope?: IntegrationScope;
836
+ scopeId?: string;
837
+ config?: undefined;
838
+ connectionId?: string;
839
+ channelId?: string;
840
+ displayName?: string;
841
+ icon?: string;
842
+ availableVersion?: string;
843
+ reinstallRequestedAt?: string;
844
+ };
845
+ declare class IntegrationsApi extends ApiBase {
846
+ /**
847
+ * List the integrations EFFECTIVE for this agent — explicit agent-scope
848
+ * installs plus driven activations (google, myob, xero, google-chat, …)
849
+ * and inherited org-scope installs, discriminated by `source`.
850
+ */
851
+ listIntegrations(): Promise<{
852
+ integrations: AgentIntegrationListEntry[];
853
+ }>;
854
+ getIntegrationConfig(integrationId: string): Promise<IntegrationConfigResult>;
855
+ updateIntegrationConfig(integrationId: string, config: Record<string, unknown>): Promise<void>;
856
+ installIntegration(integrationId: string, options?: {
857
+ version?: string;
858
+ config?: Record<string, unknown>;
859
+ }): Promise<IntegrationInstall>;
860
+ removeIntegration(integrationId: string): Promise<IntegrationInstall>;
861
+ getOAuthUrl(provider: string, scopes?: string[], options?: {
862
+ shop?: string;
863
+ }): Promise<{
864
+ url: string;
865
+ provider: string;
866
+ expiresIn: number;
867
+ }>;
868
+ getOAuthStatus(provider: string): Promise<{
869
+ provider: string;
870
+ connected: boolean;
871
+ config?: Record<string, string>;
872
+ }>;
873
+ getRegistry(): Promise<{
874
+ integrations: RegistryEntry[];
875
+ }>;
1009
876
  }
1010
- //# sourceMappingURL=search.d.ts.map
877
+ //# sourceMappingURL=integrations.d.ts.map
1011
878
  //#endregion
1012
- //#region src/domains/webhooks.d.ts
1013
- interface AgentWebhook {
1014
- webhookId: string;
879
+ //#region src/domains/workspace.d.ts
880
+ /** Response of GET /agent/workspace (services/agents). */
881
+ interface AgentWorkspaceInfo {
882
+ templateKey?: string;
883
+ defaultModel?: string;
884
+ installedFrom?: {
885
+ templateKey: string;
886
+ authorTenantId: string;
887
+ version: number;
888
+ };
889
+ runtime?: string;
890
+ teams?: {
891
+ teamId: string;
892
+ name: string;
893
+ description?: string;
894
+ parentTeamId?: string;
895
+ }[];
896
+ projects?: {
897
+ projectId: string;
898
+ name: string;
899
+ description?: string;
900
+ status: string;
901
+ parentProjectId?: string;
902
+ }[];
903
+ teamIds?: string[];
904
+ projectIds?: string[];
905
+ }
906
+ declare class WorkspaceApi extends ApiBase {
907
+ /**
908
+ * GET /agent/workspace — workspace config for the authenticated agent
909
+ * (template assignment, default model, org roster).
910
+ */
911
+ getWorkspace(): Promise<AgentWorkspaceInfo>;
912
+ /**
913
+ * GET /templates/{key}/files — persona/workspace file contents for a
914
+ * template the agent has access to. Pass `version` to pin to the version
915
+ * the agent was installed from (omit → the endpoint resolves `latest`).
916
+ */
917
+ getTemplateFiles(templateKey: string, opts?: {
918
+ version?: number;
919
+ }): Promise<{
920
+ files: Record<string, string>;
921
+ }>;
922
+ }
923
+ //# sourceMappingURL=workspace.d.ts.map
924
+ //#endregion
925
+ //#region src/domains/sync.d.ts
926
+ interface SyncAgentInfo {
927
+ agentId: string;
1015
928
  tenantId: string;
929
+ displayName: string;
930
+ s3Prefix: string;
931
+ status: "stale" | "syncing" | "synced";
932
+ fileCount?: number;
933
+ totalSize?: number;
934
+ lastSync?: string;
935
+ }
936
+ interface SyncManifestEntry {
937
+ hash: string;
938
+ size: number;
939
+ modified: string;
940
+ etag?: string;
941
+ storageClass?: string;
942
+ compressed?: boolean;
943
+ }
944
+ interface SyncManifest {
945
+ version: 1;
1016
946
  agentId: string;
1017
- name: string;
1018
- provider: string;
1019
- active: boolean;
1020
- createdBy: string;
1021
- createdAt: string;
1022
- updatedAt: string;
947
+ lastSync: string;
948
+ files: Record<string, SyncManifestEntry>;
1023
949
  }
1024
- interface CreatedAgentWebhook extends AgentWebhook {
950
+ interface SyncPresignedUrl {
951
+ path: string;
1025
952
  url: string;
1026
- signingSecret: string;
953
+ expiresAt: string;
1027
954
  }
1028
- interface AgentWebhookDelivery {
1029
- deliveryId: string;
1030
- webhookId: string;
1031
- status: string;
1032
- attempts: number;
1033
- createdAt: string;
1034
- deliveredAt?: string;
955
+ interface SyncConfirmedUpload {
956
+ filePath: string;
957
+ hash: string;
958
+ size: number;
959
+ storageClass: "STANDARD" | "GLACIER_IR";
960
+ syncedAt: string;
1035
961
  }
1036
- declare class WebhooksApi extends ApiBase {
1037
- createWebhook(args: {
1038
- name: string;
1039
- provider?: "generic" | "github" | "stripe" | "slack";
1040
- }): Promise<CreatedAgentWebhook>;
1041
- listWebhooks(): Promise<AgentWebhook[]>;
1042
- deleteWebhook(webhookId: string): Promise<{
1043
- webhookId: string;
1044
- active: false;
1045
- }>;
1046
- rotateWebhookSecret(webhookId: string): Promise<{
1047
- webhookId: string;
1048
- signingSecret: string;
1049
- }>;
1050
- listWebhookDeliveries(webhookId: string): Promise<AgentWebhookDelivery[]>;
962
+ interface SyncReconstructFile {
963
+ path: string;
964
+ size: number;
965
+ url: string;
966
+ storageClass?: string;
967
+ compressed?: boolean;
1051
968
  }
1052
- //# sourceMappingURL=webhooks.d.ts.map
1053
- //#endregion
1054
- //#region src/domains/chat.d.ts
1055
- declare class ChatApi extends ApiBase {
1056
- ensureDirectConversation(identityId: string): Promise<{
1057
- conversationId: string;
1058
- identityId: string;
1059
- tenantId: string;
1060
- userId: string;
1061
- displayName: string;
1062
- created: boolean;
969
+ interface SyncReconstructBundle {
970
+ agentId: string;
971
+ mode: "full" | "active" | "memory";
972
+ fileCount: number;
973
+ totalSize: number;
974
+ files: SyncReconstructFile[];
975
+ expiresAt: string;
976
+ }
977
+ interface SyncAgentStats {
978
+ agentId: string;
979
+ standardBytes: number;
980
+ glacierBytes: number;
981
+ fileCount: number;
982
+ lastSyncAt: string | null;
983
+ }
984
+ interface SyncFileEntry {
985
+ filePath: string;
986
+ size: number;
987
+ modified: string;
988
+ contentHash: string;
989
+ storageClass?: string;
990
+ compressed?: boolean;
991
+ }
992
+ interface SyncSessionEntry {
993
+ sessionId: string;
994
+ size: number;
995
+ lastModified: string;
996
+ storageClass?: string;
997
+ isArchived: boolean;
998
+ }
999
+ interface SyncSessionContent {
1000
+ sessionId: string;
1001
+ content: string;
1002
+ compressed: boolean;
1003
+ }
1004
+ interface SharedFileEntry {
1005
+ filePath: string;
1006
+ fileName: string;
1007
+ size: number;
1008
+ contentType?: string;
1009
+ }
1010
+ declare class SyncApi extends ApiBase {
1011
+ syncRegister(args?: {
1012
+ displayName?: string;
1013
+ }): Promise<{
1014
+ agent: SyncAgentInfo;
1063
1015
  }>;
1064
- presignAttachments(files: {
1065
- filename: string;
1066
- mimeType: string;
1067
- size: number;
1068
- }[]): Promise<{
1069
- attachments: {
1070
- id: string;
1071
- uploadUrl: string;
1072
- uploadHeaders: Record<string, string>;
1073
- downloadUrl: string;
1074
- s3Key: string;
1075
- expiresAt: string;
1016
+ syncGetManifest(): Promise<SyncManifest>;
1017
+ syncPresign(args: {
1018
+ files: {
1019
+ path: string;
1020
+ operation: "put" | "get";
1021
+ contentType?: string;
1076
1022
  }[];
1077
- }>;
1078
- recordActivity(data: {
1079
- userId?: string;
1080
- channel: string;
1081
- role: "user" | "assistant";
1082
1023
  }): Promise<{
1083
- recorded: boolean;
1024
+ urls: SyncPresignedUrl[];
1084
1025
  }>;
1085
- }
1086
- //# sourceMappingURL=chat.d.ts.map
1087
- //#endregion
1088
- //#region src/domains/connect-credentials.d.ts
1089
- declare class ConnectCredentialsApi extends ApiBase {
1090
- /**
1091
- * Returns every connected Google account for the agent. Multi-account by
1092
- * design the openclaw-google plugin requires the LLM to pass `email`
1093
- * explicitly to `google_run_command` so an account is always selected
1094
- * deliberately.
1095
- *
1096
- * 2026-05-14 (connections-redesign PR 1): the legacy flat shape (`email`,
1097
- * `refreshToken`, `accessToken`, etc., populated from the default account)
1098
- * is gone. Iterate over `accounts`.
1099
- */
1100
- getGoogleCredentials(): Promise<{
1101
- accounts: {
1102
- email: string;
1103
- refreshToken: string;
1104
- clientId: string;
1105
- clientSecret: string;
1106
- displayName?: string;
1107
- connectedAt?: string;
1108
- }[];
1026
+ syncConfirmUpload(args: {
1027
+ filePath: string;
1028
+ hash: string;
1029
+ size: number;
1030
+ storageClass?: "STANDARD" | "GLACIER_IR";
1031
+ }): Promise<SyncConfirmedUpload>;
1032
+ syncReconstruct(args: {
1033
+ mode: "full" | "active" | "memory";
1034
+ }): Promise<SyncReconstructBundle>;
1035
+ syncGetStats(): Promise<SyncAgentStats>;
1036
+ syncListFiles(args?: {
1037
+ prefix?: string;
1038
+ }): Promise<{
1039
+ files: SyncFileEntry[];
1109
1040
  }>;
1110
- disconnectGoogleAccount(email: string): Promise<{
1111
- accounts: {
1112
- email: string;
1113
- displayName?: string;
1114
- connectedAt?: string;
1115
- }[];
1041
+ syncListSessions(): Promise<{
1042
+ sessions: SyncSessionEntry[];
1116
1043
  }>;
1117
- getGoogleChatCredentials(): Promise<{
1118
- email: string;
1119
- refreshToken: string;
1120
- clientId: string;
1121
- clientSecret: string;
1122
- displayName?: string;
1044
+ syncGetSession(sessionId: string): Promise<SyncSessionContent>;
1045
+ syncDeleteFile(filePath: string): Promise<{
1046
+ removed: boolean;
1047
+ }>;
1048
+ sharedListFiles(args: {
1049
+ scope: "org" | "team" | "project";
1050
+ scopeId: string;
1051
+ limit?: number;
1052
+ cursor?: string;
1053
+ }): Promise<{
1054
+ files: SharedFileEntry[];
1055
+ nextCursor: string | null;
1056
+ }>;
1057
+ sharedDownloadUrl(args: {
1058
+ scope: "org" | "team" | "project";
1059
+ scopeId: string;
1060
+ filePath: string;
1061
+ }): Promise<{
1062
+ downloadUrl: string;
1063
+ expiresIn: number;
1123
1064
  }>;
1065
+ }
1066
+ //# sourceMappingURL=sync.d.ts.map
1067
+ //#endregion
1068
+ //#region src/domains/knowledge.d.ts
1069
+ type KnowledgeScopeType = "org" | "team" | "project";
1070
+ interface KnowledgeScope {
1071
+ scopeType: KnowledgeScopeType;
1072
+ scopeId: string;
1073
+ name: string;
1074
+ }
1075
+ interface KnowledgeSearchHit {
1076
+ id: string;
1077
+ text: string;
1078
+ /** Normalized relevance in (0,1]; higher = closer. */
1079
+ score: number;
1080
+ scopeType: KnowledgeScopeType;
1081
+ scopeId: string;
1124
1082
  /**
1125
- * Fetch decrypted credentials for ONE specific connection by its
1126
- * stable connectionId (connection-scoped, vs the provider-scoped
1127
- * `get<Provider>Credentials` helpers). Used by the daemon to resolve
1128
- * a Custom Connection-driven integration's credentials from the
1129
- * exact connection it was installed from — every custom connection
1130
- * shares the `custom` provider id, so provider-scoping is ambiguous.
1131
- *
1132
- * For custom connections `accessToken` is the JSON-encoded secret
1133
- * bundle (the daemon un-bundles it); non-secret fields are on
1134
- * `providerMetadata`. The endpoint enforces that the connection is in
1135
- * the calling agent's effective scope (403 otherwise).
1083
+ * Provenance of the hit. All live results are `"doc"`; `"fact"` only ever
1084
+ * appears for legacy vectors indexed before the facts primitive was removed
1085
+ * (the search index stays tolerant of them). Treat every hit as a doc.
1136
1086
  */
1137
- getConnectionCredentials(connectionId: string): Promise<{
1138
- provider: string;
1139
- connectionId: string;
1140
- accountIdentifier?: string;
1141
- accessToken?: string;
1142
- providerMetadata?: Record<string, unknown>;
1143
- [key: string]: unknown;
1144
- }>;
1087
+ source: "doc" | "fact";
1088
+ /** The canonical file under shared/<scope>/ (present on doc hits). */
1089
+ filePath?: string;
1090
+ /** Legacy-only: the id of a pre-removal fact vector. */
1091
+ factId?: string;
1092
+ }
1093
+ interface KnowledgeSearchResult {
1094
+ results: KnowledgeSearchHit[];
1095
+ /** True when fan-out breadth was capped (more member scopes than the cap). */
1096
+ truncatedScopes: boolean;
1097
+ }
1098
+ interface KnowledgeProfileLink {
1099
+ label: string;
1100
+ url: string;
1101
+ }
1102
+ interface KnowledgeProfile {
1103
+ scopeType: KnowledgeScopeType;
1104
+ scopeId: string;
1105
+ about: string | null;
1106
+ description: string | null;
1107
+ links: KnowledgeProfileLink[];
1108
+ updatedAt: string | null;
1109
+ updatedBy: string | null;
1110
+ }
1111
+ type ChangeRequestResourceType = "doc" | "profile";
1112
+ type ChangeRequestOperation = "create" | "update" | "delete";
1113
+ type ChangeRequestStatus = "open" | "approved" | "rejected" | "withdrawn" | "superseded";
1114
+ type ChangeRequestActorKind = "human" | "agent";
1115
+ /** Public projection of a change request (mirrors `PublicChangeRequest` in services/org). */
1116
+ interface KnowledgeChangeRequest {
1117
+ changeRequestId: string;
1118
+ scopeType: KnowledgeScopeType;
1119
+ scopeId: string;
1120
+ resourceType: ChangeRequestResourceType;
1121
+ operation: ChangeRequestOperation;
1122
+ targetPath: string | null;
1123
+ baseVersionId: string | null;
1124
+ proposedContentType: string | null;
1125
+ status: ChangeRequestStatus;
1126
+ proposerId: string;
1127
+ proposerKind: ChangeRequestActorKind;
1128
+ rationale: string;
1129
+ reviewerId: string | null;
1130
+ reviewerKind: ChangeRequestActorKind | null;
1131
+ reviewedAt: string | null;
1132
+ reviewNote: string | null;
1133
+ appliedRef: string | null;
1134
+ createdAt: string;
1135
+ updatedAt: string;
1136
+ }
1137
+ /** Per-type proposal payload for `proposeScopeChange`. */
1138
+ interface ProposeScopeChangeInput {
1139
+ resourceType: ChangeRequestResourceType;
1140
+ operation: ChangeRequestOperation;
1141
+ /** Why the change is proposed — shown to the reviewer. */
1142
+ rationale: string;
1143
+ /** doc: the path the proposal applies to (e.g. designs/data-center.md). */
1144
+ targetPath?: string;
1145
+ /** doc create/update: the staged body to upload (markdown or other text). */
1146
+ content?: string;
1147
+ /** doc create/update: content type of the staged body (default text/markdown). */
1148
+ contentType?: string;
1149
+ /** profile: the proposed value ({ about, description, links }). */
1150
+ proposedValue?: unknown;
1151
+ }
1152
+ interface KnowledgeDoc {
1153
+ filePath: string;
1154
+ fileName: string;
1155
+ contentType?: string;
1156
+ size: number;
1157
+ uploadedBy?: string;
1158
+ createdAt: string;
1159
+ updatedAt: string;
1160
+ }
1161
+ declare class KnowledgeApi extends ApiBase {
1145
1162
  /**
1146
- * @deprecated Returns a single primary credential blob (legacy "pick-the-
1147
- * default-connection" shape). Use `getGithubAccounts()` for the multi-
1148
- * account shape required by Pattern A explicit selector args on every
1149
- * tool. Retained because the `@alfe.ai/github-mcp` proxy is the
1150
- * only consumer that knows about Pattern A; legacy env-interpolation
1151
- * callers will keep hitting `/credentials` until they move to the proxy.
1163
+ * Semantic search across the agent's member scopes. Fan-out is gated
1164
+ * server-side by `listScopes` set-inclusion (fail-closed). Pass
1165
+ * `scopeType` + `scopeId` to narrow to one scope; a non-member scope
1166
+ * yields empty results (never a cross-scope leak).
1152
1167
  */
1153
- getGithubCredentials(): Promise<{
1154
- login: string;
1155
- accessToken: string;
1168
+ knowledgeSearch(query: string, opts?: {
1169
+ limit?: number;
1170
+ scopeType?: KnowledgeScopeType;
1171
+ scopeId?: string;
1172
+ }): Promise<KnowledgeSearchResult>;
1173
+ /** Enumerate the scopes (org + teams + projects) this agent belongs to. */
1174
+ listScopes(): Promise<{
1175
+ scopes: KnowledgeScope[];
1156
1176
  }>;
1177
+ /** Read a scope's structured knowledge profile (after membership check). */
1178
+ getScopeProfile(scopeType: KnowledgeScopeType, scopeId: string): Promise<KnowledgeProfile>;
1157
1179
  /**
1158
- * Pattern A: multi-account credential fetch for GitHub.
1159
- *
1160
- * Returns every agent-scoped GitHub connection. The caller is expected
1161
- * to require a `login` selector on every credential-touching tool and
1162
- * look up the matching account at dispatch time.
1163
- *
1164
- * GitHub OAuth tokens have no expiry (`tokenLifecycle: "no_expiry"`),
1165
- * so there is intentionally no `refreshGithubAccountToken` method — if
1166
- * a token is revoked the user must re-run the OAuth flow.
1167
- *
1168
- * Returned `accounts[i].login` is the GitHub username — the stable
1169
- * cross-session identifier the LLM should pass.
1180
+ * Open a change request against a scope's knowledge resource. For a doc
1181
+ * create/update, `services/org` returns a presigned staging PUT; this method
1182
+ * uploads the proposed `content` to it (echoing the same Content-Type that
1183
+ * was signed), mirroring `writeScopeDoc`. The staged body is applied to the
1184
+ * canonical doc attributed to this agent — only when a reviewer approves.
1170
1185
  */
1171
- getGithubAccounts(): Promise<{
1172
- accounts: {
1173
- connectionId: string;
1174
- accountIdentifier: string;
1175
- displayName: string | null;
1176
- connectedAt: string;
1177
- accessToken: string;
1178
- login: string;
1179
- scopes: string;
1180
- }[];
1181
- }>;
1186
+ proposeScopeChange(scopeType: KnowledgeScopeType, scopeId: string, input: ProposeScopeChangeInput): Promise<KnowledgeChangeRequest>;
1182
1187
  /**
1183
- * @deprecated Returns a single primary credential blob (legacy "pick-the-
1184
- * default-connection" shape). Use `getXeroAccounts()` for the multi-
1185
- * account shape required by Pattern A — explicit selector args on every
1186
- * tool. This method will be removed once all consumers migrate.
1188
+ * List the agent's OWN change requests in a scope (filtered server-side to
1189
+ * this agent as proposer). Pass `status` to narrow to open / approved / etc.
1187
1190
  */
1188
- getXeroCredentials(): Promise<{
1189
- accessToken: string;
1190
- accessTokenExpiresAt: string;
1191
- xeroTenantId: string;
1191
+ listScopeChangeRequests(scopeType: KnowledgeScopeType, scopeId: string, opts?: {
1192
+ status?: ChangeRequestStatus;
1193
+ limit?: number;
1194
+ cursor?: string;
1195
+ }): Promise<{
1196
+ changeRequests: KnowledgeChangeRequest[];
1197
+ nextCursor: string | null;
1192
1198
  }>;
1193
- /**
1194
- * Pattern A: multi-account credential fetch for Xero. Returns every
1195
- * agent-scoped Xero connection. The caller is expected to require a
1196
- * selector arg (e.g. `xeroTenantId`) on every credential-touching tool
1197
- * and look up the matching account by that selector at dispatch time.
1198
- *
1199
- * `xeroTenantId` is the model-facing organisation selector. The separate
1200
- * `accountIdentifier` is the Connect persistence key used for refresh and
1201
- * may be an email; never substitute one for the other.
1202
- */
1203
- getXeroAccounts(): Promise<{
1204
- accounts: {
1205
- connectionId: string;
1206
- accountIdentifier: string;
1207
- displayName: string | null;
1208
- connectedAt: string;
1209
- accessToken: string;
1210
- accessTokenExpiresAt: string;
1211
- xeroTenantId: string;
1212
- }[];
1213
- }>;
1214
- refreshXeroToken(): Promise<{
1215
- accessToken: string;
1216
- expiresAt: string;
1217
- }>;
1218
- /**
1219
- * Refresh a specific Xero Connection by its exact `accountIdentifier` from
1220
- * `getXeroAccounts()`. Do not substitute `xeroTenantId`: current Xero OAuth
1221
- * rows may use the account email as their persistence key even when a sole
1222
- * organisation tenant ID is available in provider metadata.
1223
- */
1224
- refreshXeroAccountToken(accountIdentifier: string): Promise<{
1225
- accessToken: string;
1226
- accessTokenExpiresAt: string;
1227
- expiresAt: string;
1199
+ /** List a scope's docs (the org-files corpus; mirrored to shared/<scope>/). */
1200
+ listScopeDocs(scopeType: KnowledgeScopeType, scopeId: string, opts?: {
1201
+ limit?: number;
1202
+ cursor?: string;
1203
+ }): Promise<{
1204
+ files: KnowledgeDoc[];
1205
+ nextCursor: string | null;
1228
1206
  }>;
1229
1207
  /**
1230
- * @deprecated Returns a single primary credential blob (legacy "pick-the-
1231
- * default-connection" shape). Use `getNotionAccounts()` for the multi-
1232
- * account shape required by Pattern A.
1208
+ * Read the full text of a scope doc. Resolves a presigned download URL
1209
+ * from `services/org`, then fetches the bytes directly from S3 (the one
1210
+ * legitimate raw fetch in a plugin — same pattern as sync).
1233
1211
  */
1234
- getNotionCredentials(): Promise<{
1235
- accessToken: string;
1236
- workspaceId: string;
1237
- workspaceName: string;
1212
+ readScopeDoc(scopeType: KnowledgeScopeType, scopeId: string, filePath: string, opts?: {
1213
+ maxBytes?: number;
1214
+ }): Promise<{
1215
+ filePath: string;
1216
+ text: string;
1238
1217
  }>;
1239
1218
  /**
1240
- * Pattern A: multi-account credential fetch for Notion. Returns every
1241
- * agent-scoped Notion connection. The caller is expected to require a
1242
- * selector arg (e.g. `workspaceId`) on every credential-touching tool.
1243
- *
1244
- * Returned `accounts[i].accountIdentifier` is the Notion workspaceId.
1219
+ * Write (create or overwrite) a scope doc. Two-step presigned upload:
1220
+ * `services/org` returns a signed URL plus `requiredHeaders` (author /
1221
+ * authorKind / message as `x-amz-meta-*`) that MUST be sent verbatim on
1222
+ * the PUT, alongside the same `Content-Type` that was signed. Author and
1223
+ * authorKind are server-set from the agent token — never trusted here.
1245
1224
  */
1246
- getNotionAccounts(): Promise<{
1247
- accounts: {
1248
- connectionId: string;
1249
- accountIdentifier: string;
1250
- displayName: string | null;
1251
- connectedAt: string;
1252
- accessToken: string;
1253
- workspaceId: string;
1254
- workspaceName: string;
1255
- }[];
1225
+ writeScopeDoc(scopeType: KnowledgeScopeType, scopeId: string, filePath: string, content: string, opts?: {
1226
+ contentType?: string;
1227
+ message?: string;
1228
+ }): Promise<{
1229
+ filePath: string;
1256
1230
  }>;
1257
- /**
1258
- * @deprecated Returns a single primary Atlassian Connection's credentials
1259
- * (one OAuth user, one cloudId) — the legacy "pick-the-default-connection"
1260
- * shape. Atlassian is multi-site by nature (each OAuth user may have
1261
- * access to multiple Cloud sites), so Pattern A plugins MUST use
1262
- * `getAtlassianAccounts()` to discover the full set and dispatch via
1263
- * the `cloudId` selector arg.
1264
- */
1265
- getAtlassianCredentials(): Promise<{
1266
- accessToken: string;
1267
- refreshToken: string;
1268
- accessTokenExpiresAt: string;
1269
- cloudId: string;
1270
- siteName: string;
1271
- siteUrl: string;
1272
- email: string;
1273
- enabledProducts: string[];
1274
- clientId: string;
1275
- clientSecret: string;
1231
+ }
1232
+ //# sourceMappingURL=knowledge.d.ts.map
1233
+ //#endregion
1234
+ //#region src/domains/mobile.d.ts
1235
+ /** Response of GET /mobile/numbers for an agent (services/mobile). */
1236
+ interface MobileNumberInfo {
1237
+ phoneNumber: string;
1238
+ countryCode: string;
1239
+ monthlyPrice?: number;
1240
+ status: string;
1241
+ errorMessage?: string;
1242
+ }
1243
+ /** One purchasable number from GET /mobile/numbers/search. */
1244
+ interface MobileAvailableNumber {
1245
+ number: string;
1246
+ friendlyName: string;
1247
+ locality: string;
1248
+ region: string;
1249
+ country: string;
1250
+ }
1251
+ /** Approved WhatsApp content template from GET /mobile/whatsapp/templates. */
1252
+ interface WhatsAppTemplate {
1253
+ contentSid: string;
1254
+ name: string;
1255
+ language: string;
1256
+ body: string;
1257
+ variables: Record<string, string>;
1258
+ category?: string;
1259
+ }
1260
+ declare class MobileApi extends ApiBase {
1261
+ getMobileNumber(): Promise<MobileNumberInfo>;
1262
+ searchMobileNumbers(args?: {
1263
+ country?: string;
1264
+ query?: string;
1265
+ }): Promise<{
1266
+ numbers: MobileAvailableNumber[];
1267
+ monthlyPrice: number;
1276
1268
  }>;
1277
- refreshAtlassianToken(): Promise<{
1278
- accessToken: string;
1279
- expiresAt: string;
1269
+ assignMobileNumber(args: {
1270
+ phoneNumber: string;
1271
+ countryCode: string;
1272
+ }): Promise<{
1273
+ phoneNumber: string;
1274
+ countryCode: string;
1275
+ status: "pending";
1280
1276
  }>;
1281
- /**
1282
- * Pattern A: multi-account / multi-site credential fetch for Atlassian.
1283
- *
1284
- * Returns every agent-scoped Atlassian Connection. Each Connection is
1285
- * one OAuth user with a single access token and N accessible Cloud
1286
- * sites (`availableSites`). The caller is expected to:
1287
- *
1288
- * 1. Flatten (connection × cloudId) into one MCP child per site.
1289
- * 2. Require a `cloudId` selector on every credential-touching tool.
1290
- * 3. Use the access token bound to the Connection that owns the
1291
- * requested `cloudId` (Atlassian shares one access token across
1292
- * all sites accessible to the OAuth user).
1293
- *
1294
- * Per-account token refresh uses `refreshAtlassianAccountToken(email)`
1295
- * — refreshing one Connection rotates its single access token, which
1296
- * then applies to every cloudId for that Connection.
1297
- *
1298
- * Returned `accounts[i].accountIdentifier` is the OAuth user's email
1299
- * — the stable cross-session identifier for refresh purposes. The LLM
1300
- * never sees this directly: it picks a site via the `cloudId` arg
1301
- * instead.
1302
- */
1303
- getAtlassianAccounts(): Promise<{
1304
- accounts: {
1305
- connectionId: string;
1306
- accountIdentifier: string;
1307
- displayName: string | null;
1308
- connectedAt: string;
1309
- accessToken: string;
1310
- accessTokenExpiresAt: string;
1311
- clientId: string;
1312
- clientSecret: string;
1313
- cloudId: string;
1314
- siteName: string;
1315
- siteUrl: string;
1316
- availableSites: {
1317
- id: string;
1318
- url: string;
1319
- name: string;
1320
- scopes?: string[];
1321
- avatarUrl?: string;
1322
- }[];
1323
- }[];
1277
+ releaseMobileNumber(): Promise<{
1278
+ released: true;
1324
1279
  }>;
1325
- /**
1326
- * Pattern A: refresh a specific Atlassian Connection by `accountIdentifier`
1327
- * (the OAuth user's email).
1328
- *
1329
- * Atlassian rotates refresh tokens (`rotatesRefreshToken: true`); the
1330
- * server-side per-account refresh endpoint handles rotation and
1331
- * persistence. Refreshing one Connection updates its single access
1332
- * token, which applies to every accessible Cloud site (cloudId) for
1333
- * that OAuth user.
1334
- *
1335
- * Returns the new access token + expiry. The proxy is responsible for
1336
- * fanning the new token out to every child server it spawned for
1337
- * cloudIds owned by this Connection.
1338
- */
1339
- refreshAtlassianAccountToken(accountIdentifier: string): Promise<{
1340
- accessToken: string;
1341
- accessTokenExpiresAt: string;
1342
- expiresAt: string;
1280
+ sendSms(args: {
1281
+ to: string;
1282
+ body: string;
1283
+ }): Promise<{
1284
+ sent: true;
1285
+ sid: string;
1343
1286
  }>;
1344
- /**
1345
- * @deprecated Returns a single primary credential blob (legacy "pick-the-
1346
- * default-connection" shape). Use `getMYOBAccounts()` for the multi-
1347
- * account shape required by Pattern A.
1348
- */
1349
- getMYOBCredentials(): Promise<{
1350
- accessToken: string;
1351
- accessTokenExpiresAt: string;
1352
- myobBusinessId: string;
1353
- clientId: string;
1287
+ startOutboundCall(args: {
1288
+ to: string;
1289
+ }): Promise<{
1290
+ callSid: string;
1291
+ status: string;
1354
1292
  }>;
1355
- /**
1356
- * Pattern A: multi-account credential fetch for MYOB. Returns every
1357
- * agent-scoped MYOB connection. The caller is expected to require a
1358
- * selector arg (e.g. `myobBusinessId` / `accountIdentifier`) on every
1359
- * credential-touching tool.
1360
- *
1361
- * Returned `accounts[i].accountIdentifier` is the MYOB businessId.
1362
- */
1363
- getMYOBAccounts(): Promise<{
1364
- accounts: {
1365
- connectionId: string;
1366
- accountIdentifier: string;
1367
- displayName: string | null;
1368
- connectedAt: string;
1369
- accessToken: string;
1370
- accessTokenExpiresAt: string;
1371
- myobBusinessId: string;
1372
- clientId: string;
1373
- }[];
1293
+ getWhatsAppSession(to: string): Promise<{
1294
+ active: boolean;
1295
+ expiresAt?: string;
1374
1296
  }>;
1375
- refreshMYOBToken(): Promise<{
1376
- accessToken: string;
1377
- expiresAt: string;
1297
+ sendWhatsAppMessage(args: {
1298
+ to: string;
1299
+ body: string;
1300
+ }): Promise<{
1301
+ sent: true;
1302
+ sid: string;
1303
+ }>;
1304
+ sendWhatsAppTemplate(args: {
1305
+ to: string;
1306
+ contentSid: string;
1307
+ contentVariables: Record<string, string>;
1308
+ bodyPreview?: string;
1309
+ }): Promise<{
1310
+ sent: true;
1311
+ sid: string;
1312
+ }>;
1313
+ listWhatsAppTemplates(): Promise<{
1314
+ templates: WhatsAppTemplate[];
1315
+ }>;
1316
+ }
1317
+ //# sourceMappingURL=mobile.d.ts.map
1318
+ //#endregion
1319
+ //#region src/domains/remote.d.ts
1320
+ interface RemoteSessionInfo {
1321
+ sessionId: string;
1322
+ agentId: string;
1323
+ surface: "browser" | "terminal";
1324
+ status: "agent_driving" | "awaiting_human" | "human_in_control" | "resuming" | "completed" | "expired" | "failed";
1325
+ url?: string;
1326
+ instructions?: string;
1327
+ requestedAt?: string;
1328
+ }
1329
+ declare class RemoteApi extends ApiBase {
1330
+ requestBrowserTakeover(args: {
1331
+ instructions: string;
1332
+ url?: string;
1333
+ conversationId?: string;
1334
+ }): Promise<{
1335
+ sessionId: string;
1336
+ status: string;
1337
+ }>;
1338
+ getRemoteSession(sessionId: string): Promise<RemoteSessionInfo>;
1339
+ completeRemoteSession(sessionId: string): Promise<{
1340
+ ok: boolean;
1378
1341
  }>;
1342
+ }
1343
+ //# sourceMappingURL=remote.d.ts.map
1344
+ //#endregion
1345
+ //#region src/domains/self.d.ts
1346
+ /** Voice settings — core agent config. Mirrors `VoiceConfig` in `@alfe/types`. */
1347
+ interface AgentVoiceConfig {
1348
+ /** ElevenLabs voice ID; platform default when unset. */
1349
+ voiceId?: string;
1350
+ ttsModel?: string;
1351
+ enabled?: boolean;
1352
+ }
1353
+ /**
1354
+ * The agent's own public identity, as returned by `updateSelf`, `generateAvatar`,
1355
+ * `presignAvatar`'s finalize (`finalizeAvatar`). This is the public agent
1356
+ * projection; only the identity-relevant fields are typed here — the response
1357
+ * carries the full public agent record.
1358
+ */
1359
+ interface AgentSelf {
1360
+ agentId: string;
1361
+ tenantId: string;
1362
+ name: string;
1363
+ avatarUrl?: string;
1364
+ voiceConfig?: AgentVoiceConfig;
1365
+ status: string;
1366
+ }
1367
+ /** Result of `presignAvatar` — the agent PUTs bytes to `uploadUrl`, then finalizes with `s3Key`. */
1368
+ interface AgentAvatarPresign {
1369
+ /** Presigned PUT URL to upload the image bytes to. */
1370
+ uploadUrl: string;
1371
+ /** Object key — echoed back to `finalizeAvatar`. */
1372
+ s3Key: string;
1373
+ /** Stable public URL the avatar will be served from once finalized. */
1374
+ publicUrl: string;
1375
+ /** ISO expiry of the presigned PUT URL. */
1376
+ expiresAt: string;
1377
+ }
1378
+ /** A voice in the platform catalogue (ElevenLabs), from `listVoices`. */
1379
+ interface AgentVoice {
1380
+ id: string;
1381
+ name: string;
1382
+ previewUrl: string;
1383
+ description: string;
1384
+ labels: Record<string, string>;
1385
+ category: string;
1386
+ }
1387
+ declare class SelfApi extends ApiBase {
1388
+ /** Update the agent's own name and/or voice config. Returns the updated agent. */
1389
+ updateSelf(update: {
1390
+ name?: string;
1391
+ voiceConfig?: AgentVoiceConfig;
1392
+ }): Promise<AgentSelf>;
1379
1393
  /**
1380
- * Pattern A: refresh one MYOB Connection by its stable
1381
- * `accountIdentifier` (the MYOB business id returned by
1382
- * `getMYOBAccounts()`).
1394
+ * Generate the agent's own avatar from a text prompt. The image is generated,
1395
+ * stored, and set on the agent server-side; returns the updated agent.
1383
1396
  *
1384
- * MYOB refresh tokens belong to individual Connection rows. A
1385
- * multi-business client must use this method instead of refreshing the
1386
- * primary Connection and copying that access token into every cached
1387
- * business client.
1397
+ * ASYNC (same reason as `generateImage`): avatar gen runs `gpt-image-1`
1398
+ * (30–60s) which exceeds the API Gateway 30s ceiling, so this enqueues a job
1399
+ * (`POST /agent/avatar/generate` `jobId`) then polls (`GET /agent/avatar/{jobId}`)
1400
+ * until the avatar is set. Signature unchanged — the plugin is unaffected.
1388
1401
  */
1389
- refreshMYOBAccountToken(accountIdentifier: string): Promise<{
1390
- accessToken: string;
1391
- accessTokenExpiresAt: string;
1392
- expiresAt: string;
1393
- }>;
1402
+ generateAvatar(args: {
1403
+ prompt: string;
1404
+ }): Promise<AgentSelf>;
1394
1405
  /**
1395
- * @deprecated Returns a single primary credential blob. Use
1396
- * `getSalesforceAccounts()` for the multi-account shape required by
1397
- * Pattern A.
1406
+ * Get a presigned PUT URL to upload a new avatar image. Upload the bytes to
1407
+ * `uploadUrl`, then call `finalizeAvatar(s3Key)` to set it on the agent.
1398
1408
  */
1399
- getSalesforceCredentials(): Promise<{
1400
- accessToken: string;
1401
- accessTokenExpiresAt: string;
1402
- instanceUrl: string;
1403
- orgId: string;
1404
- }>;
1409
+ presignAvatar(args: {
1410
+ mimeType: string;
1411
+ size: number;
1412
+ }): Promise<AgentAvatarPresign>;
1405
1413
  /**
1406
- * Pattern A: multi-account credential fetch for Salesforce. Returns every
1407
- * agent-scoped Salesforce connection. One OAuth grant maps to one org, so
1408
- * `accounts[i].accountIdentifier` (and `orgId`) is the Salesforce org id —
1409
- * the selector every credential-touching tool requires.
1414
+ * Finalize an avatar upload validates ownership + size, then sets the
1415
+ * agent's `avatarUrl` server-side. Returns the updated agent.
1410
1416
  */
1411
- getSalesforceAccounts(): Promise<{
1412
- accounts: {
1413
- connectionId: string;
1414
- accountIdentifier: string;
1415
- displayName: string | null;
1416
- connectedAt: string;
1417
- accessToken: string;
1418
- accessTokenExpiresAt: string;
1419
- instanceUrl: string;
1420
- orgId: string;
1421
- }[];
1417
+ finalizeAvatar(s3Key: string): Promise<AgentSelf>;
1418
+ /** List the platform voice catalogue (ElevenLabs) so the agent can pick its own voice. */
1419
+ listVoices(): Promise<{
1420
+ voices: AgentVoice[];
1422
1421
  }>;
1422
+ }
1423
+ //# sourceMappingURL=self.d.ts.map
1424
+ //#endregion
1425
+ //#region src/domains/voice.d.ts
1426
+ /** The ElevenLabs models with a pricing row — the TTS endpoint rejects any other value. */
1427
+ type VoiceTtsModel = "eleven_turbo_v2_5" | "eleven_multilingual_v2";
1428
+ interface VoiceTtsArgs {
1429
+ /** Text to synthesize (1–5000 chars — the endpoint enforces this). */
1430
+ text: string;
1431
+ /** ElevenLabs voice id; platform default when unset. */
1432
+ voiceId?: string;
1433
+ /** TTS model; `eleven_turbo_v2_5` (lower latency) when unset. */
1434
+ model?: VoiceTtsModel;
1435
+ }
1436
+ /** Raw synthesized audio plus its PCM framing (from the response headers). */
1437
+ interface VoiceTtsResult {
1438
+ /** Raw little-endian PCM samples — no container. Wrap in WAV to make a playable file. */
1439
+ audio: Buffer;
1440
+ /** Samples per second (e.g. 24000). */
1441
+ sampleRate: number;
1442
+ /** Channel count (mono = 1). */
1443
+ channels: number;
1444
+ /** Bits per sample (e.g. 16). */
1445
+ bitDepth: number;
1446
+ }
1447
+ interface VoiceSttArgs {
1448
+ /** Raw linear16 (16-bit little-endian) mono PCM samples — no WAV/container header. */
1449
+ audio: Uint8Array;
1450
+ /** Sample rate of `audio` in Hz (8000–48000). */
1451
+ sampleRate: number;
1452
+ }
1453
+ interface VoiceSttResult {
1454
+ text: string;
1455
+ /** Deepgram confidence in (0,1]. */
1456
+ confidence: number;
1457
+ }
1458
+ declare class VoiceApi extends ApiBase {
1423
1459
  /**
1424
- * Refresh the access token for a specific Salesforce org. Salesforce
1425
- * tokens aren't interchangeable across orgs, so the connection is targeted
1426
- * by `accountIdentifier` (the org id) mirrors `refreshXeroAccountToken`.
1460
+ * Text-to-speech. Returns raw PCM audio bytes plus their framing — the
1461
+ * voice service defaults to 24 kHz / mono / 16-bit. Wrap in a WAV container
1462
+ * to produce a playable file. Metered per character against the tenant
1463
+ * credit pool server-side; TTS completes regardless of metering outcome.
1427
1464
  */
1428
- refreshSalesforceAccountToken(orgId: string): Promise<{
1429
- accessToken: string;
1430
- accessTokenExpiresAt: string;
1431
- expiresAt: string;
1432
- }>;
1465
+ tts(args: VoiceTtsArgs): Promise<VoiceTtsResult>;
1433
1466
  /**
1434
- * Pattern A: multi-account credential fetch for Microsoft 365.
1435
- *
1436
- * Returns every agent-scoped Microsoft connection. The caller is expected
1437
- * to require an `email` selector on every credential-touching tool and
1438
- * look up the matching account at dispatch time.
1439
- *
1440
- * Returned `accounts[i].accountIdentifier` is the user's primary email
1441
- * (or the tid claim as fallback) — the stable cross-session identifier
1442
- * the LLM should pass.
1443
- *
1444
- * Per-account token refresh is exposed via `refreshMicrosoftAccountToken`,
1445
- * NOT `refreshXeroAccountToken` — Microsoft refresh tokens are not
1446
- * interchangeable across (tenant, user) pairs.
1467
+ * Speech-to-text. Accepts raw linear16 (16-bit LE) mono PCM NOT a WAV or
1468
+ * other container (the endpoint transcribes with a fixed linear16 encoding,
1469
+ * so a container header would be transcribed as noise). Strip any WAV header
1470
+ * and pass `sampleRate` from it before calling. Metered by transcribed
1471
+ * duration against the tenant credit pool server-side.
1447
1472
  */
1448
- getMicrosoftAccounts(): Promise<{
1449
- accounts: {
1450
- connectionId: string;
1451
- accountIdentifier: string;
1452
- displayName: string | null;
1453
- connectedAt: string;
1454
- accessToken: string;
1455
- accessTokenExpiresAt: string;
1456
- email: string;
1457
- microsoftTenantId: string;
1458
- workspaceDomain: string;
1459
- }[];
1460
- }>;
1473
+ stt(args: VoiceSttArgs): Promise<VoiceSttResult>;
1474
+ }
1475
+ //# sourceMappingURL=voice.d.ts.map
1476
+ //#endregion
1477
+ //#region src/domains/identity.d.ts
1478
+ type IdentityStatus = "anonymous" | "partial" | "identified" | "verified";
1479
+ interface IdentityDirectoryEntry {
1480
+ identityId: string;
1481
+ status: IdentityStatus;
1482
+ displayName: string;
1483
+ name?: string;
1484
+ avatarUrl?: string;
1485
+ lastSeenAt: string;
1486
+ lastSeenProvider?: string;
1487
+ messageable: boolean;
1488
+ }
1489
+ declare class IdentityApi extends ApiBase {
1461
1490
  /**
1462
- * Pattern A: refresh a specific Microsoft 365 connection by its
1463
- * `accountIdentifier`. For Microsoft, `accountIdentifier` is the user's
1464
- * email when the Graph profile fetch succeeded at connect time, and the
1465
- * Azure tenant id (`tid` claim) as fallback. Callers should pass the
1466
- * value returned by `getMicrosoftAccounts()` rather than synthesising
1467
- * an email locally.
1468
- *
1469
- * Microsoft refresh tokens are bound to a specific (tenant, user) pair —
1470
- * they are NOT interchangeable across accounts, so per-account refresh
1471
- * is mandatory. The generic /accounts/{accountIdentifier}/refresh
1472
- * endpoint walks the agent's full visible scope chain to find a matching
1473
- * connection (works for inherited team/project Microsoft connections).
1491
+ * Returns the calling agent's own identity context `{ agentId, tenantId }`
1492
+ * decoded server-side from the agent API token. Used by the
1493
+ * `@alfe.ai/openclaw-identity` plugin to bootstrap context when the
1494
+ * OpenClaw daemon doesn't plumb `ctx.agentId` through to plugin hooks.
1495
+ * Plugins should cache this for the daemon's lifetime (single-agent-per-
1496
+ * process invariant). One HTTP round-trip per process activate; not for
1497
+ * per-call use.
1474
1498
  */
1475
- refreshMicrosoftAccountToken(accountIdentifier: string): Promise<{
1476
- accessToken: string;
1477
- accessTokenExpiresAt: string;
1478
- expiresAt: string;
1499
+ whoami(): Promise<{
1500
+ agentId: string;
1501
+ tenantId: string;
1479
1502
  }>;
1480
- /**
1481
- * Disconnects one connected Microsoft 365 account for the agent, by its
1482
- * `accountIdentifier`. Hits the generic per-account disconnect route
1483
- * (`DELETE /agent/connect/microsoft/accounts/{accountIdentifier}`), which
1484
- * resolves across the agent's full effective scope chain and deletes the
1485
- * matching Connection row. Returns the remaining accounts.
1486
- *
1487
- * IMPORTANT: pass the `accountIdentifier` from `getMicrosoftAccounts()`, NOT
1488
- * a synthesised email. For Microsoft, `accountIdentifier` is the user's email
1489
- * only when the Graph profile fetch succeeded at connect time; it falls back
1490
- * to the Azure tenant id (`tid` claim) otherwise. The backend matches on
1491
- * `accountIdentifier` exactly, so passing an email would 404 on those
1492
- * fallback-identifier accounts. (This is why the param is not named `email`,
1493
- * unlike `disconnectGoogleAccount` where the identifier is always the email.)
1494
- */
1495
- disconnectMicrosoftAccount(accountIdentifier: string): Promise<{
1496
- accounts: {
1497
- accountIdentifier: string;
1498
- displayName?: string;
1499
- connectedAt?: string;
1500
- }[];
1503
+ resolveIdentity(args: {
1504
+ provider: string;
1505
+ platformId: string;
1506
+ kind?: "user" | "agent" | "service" | "bot" | "workspace";
1507
+ displayName?: string;
1508
+ }): Promise<{
1509
+ identityId: string | null;
1510
+ status: string;
1511
+ created?: boolean;
1512
+ reason?: string;
1513
+ /**
1514
+ * Flattened auriclabs permission strings for the resolved identity
1515
+ * (scope-prefixed where applicable). Empty array on miss / org service
1516
+ * outage the runtime gate fails closed in that case.
1517
+ */
1518
+ permissions: string[];
1501
1519
  }>;
1502
- /**
1503
- * Resolve the primary cTrader Connection's credentials for the calling
1504
- * agent. Unlike most providers, the cTrader Open API needs app-level auth
1505
- * (`clientId` + `clientSecret`) AND account auth (`accessToken` +
1506
- * `accountId`) on the socket, so `@alfe.ai/ctrader-mcp` self-fetches the
1507
- * full set here at startup (the atlassian/google pattern). `clientId` /
1508
- * `clientSecret` are the SST-sourced global app credentials the connect
1509
- * endpoint injects — they are never persisted on the connection. `host` is
1510
- * the resolved TLS endpoint (`live.ctraderapi.com` / `demo.ctraderapi.com`)
1511
- * derived from the selected account's live/demo flag.
1512
- */
1513
- getCTraderCredentials(): Promise<{
1514
- accessToken: string;
1515
- refreshToken: string;
1516
- accountId: string;
1517
- host: string;
1518
- clientId: string;
1519
- clientSecret: string;
1520
+ searchIdentities(args?: {
1521
+ q?: string;
1522
+ status?: string;
1523
+ limit?: number;
1524
+ }): Promise<{
1525
+ identities: unknown[];
1520
1526
  }>;
1521
- /**
1522
- * Pattern A: multi-account credential fetch for cTrader.
1523
- *
1524
- * Unlike atlassian/salesforce (one Connection row per account/site), a
1525
- * cTrader is MULTI-grant per agent: an agent may connect several distinct
1526
- * cTrader logins, each its own Connection row keyed on `accountIdentifier =
1527
- * ctid:<userId>` (Phase 1). This aggregates the *trading accounts* across
1528
- * ALL of those Connection rows — each row contributes its `availableAccounts`
1529
- * flattened, and every account carries ITS OWN grant's `accessToken` (the
1530
- * token that authenticates that account against the cTrader Open API). One
1531
- * OAuth grant still covers all accounts under that single login on one shared
1532
- * token; only the `ctidTraderAccountId` and the protobuf socket `host` (live
1533
- * vs demo) differ within a grant. Across grants the tokens differ, so the
1534
- * token is now PER-ACCOUNT rather than hoisted to the top level.
1535
- *
1536
- * `host` per account is derived from the account's `isLive` flag
1537
- * (`live.ctraderapi.com` / `demo.ctraderapi.com`) — the same mapping the
1538
- * connect provider applies server-side when an account is auto-selected.
1539
- *
1540
- * `clientId` / `clientSecret` are the SST-sourced GLOBAL app credentials the
1541
- * connect endpoint injects — identical across every Connection row (one
1542
- * cTrader app), never persisted on a connection. We take them from the first
1543
- * row that carries them.
1544
- *
1545
- * Accounts are deduped on `ctidTraderAccountId` first-wins: Spotware ids are
1546
- * globally unique across logins, so a duplicate can only appear if the same
1547
- * account somehow surfaced under two grants — first-wins keeps it
1548
- * deterministic.
1549
- *
1550
- * `accounts` may be empty (no cTrader Connection at all), in which case we
1551
- * return empty creds rather than throwing.
1552
- */
1553
- getCTraderAccounts(): Promise<{
1554
- accounts: {
1555
- ctidTraderAccountId: string;
1556
- host: string;
1557
- isLive: boolean;
1558
- brokerName?: string;
1559
- accountNumber?: string;
1560
- accessToken: string;
1561
- /**
1562
- * The stable per-grant Connection key (`ctid:<userId>`) this account
1563
- * belongs to. Every trading account under one cTrader login shares one
1564
- * grant (one OAuth token), so this is the identifier the MCP server
1565
- * passes to `refreshCTraderAccount()` to rotate the token for the whole
1566
- * grant on a `CH_ACCESS_TOKEN_INVALID` expiry. Empty string when the
1567
- * server did not supply one (legacy rows) — such an account can still
1568
- * trade with its current token but cannot self-refresh.
1569
- */
1570
- accountIdentifier: string;
1571
- }[];
1572
- clientId: string;
1573
- clientSecret: string;
1527
+ listIdentities(args?: {
1528
+ status?: IdentityStatus;
1529
+ limit?: number;
1530
+ cursor?: string;
1531
+ }): Promise<{
1532
+ identities: IdentityDirectoryEntry[];
1533
+ cursor: string | null;
1574
1534
  }>;
1575
- /**
1576
- * Pattern A: refresh a specific cTrader grant by its stable
1577
- * `accountIdentifier` (`ctid:<userId>` from `getCTraderAccounts()`).
1578
- *
1579
- * cTrader access tokens live ~30 days; the `getCTraderAccounts()` /
1580
- * credentials reads serve the STORED token without refreshing, so refresh is
1581
- * the consumer's job. `@alfe.ai/ctrader-mcp` calls this when the cTrader Open
1582
- * API rejects an account-auth with `CH_ACCESS_TOKEN_INVALID`, then re-runs
1583
- * the socket handshake with the returned `accessToken`.
1584
- *
1585
- * Refreshing one grant rotates the single OAuth token that covers EVERY
1586
- * trading account under that login. cTrader's refresh token itself does not
1587
- * expire but may rotate on refresh (`rotatesRefreshToken: true`); connect
1588
- * persists the rotated refresh token server-side, so the caller only needs
1589
- * the new `accessToken`. Mirrors `refreshXeroAccountToken`.
1590
- */
1591
- refreshCTraderAccount(accountIdentifier: string): Promise<{
1592
- accessToken: string;
1593
- accessTokenExpiresAt: string;
1594
- expiresAt: string;
1535
+ getIdentityContext(identityId: string): Promise<{
1536
+ context: unknown;
1595
1537
  }>;
1596
- /**
1597
- * @deprecated Returns a single primary credential blob. Use
1598
- * `getShopifyAccounts()` for the multi-account shape required by Pattern A
1599
- * (`@alfe.ai/shopify-mcp` keys per-shop on the myshopify domain).
1600
- */
1601
- getShopifyCredentials(): Promise<{
1602
- accessToken: string;
1603
- shopDomain: string;
1604
- shopGid: string;
1605
- shopName: string;
1606
- apiVersion: string;
1538
+ mergeIdentities(survivorId: string, args: {
1539
+ mergedId: string;
1540
+ }): Promise<{
1541
+ ok: boolean;
1542
+ error?: string;
1607
1543
  }>;
1608
- /**
1609
- * Pattern A: multi-account credential fetch for Shopify. Returns every
1610
- * agent-scoped Shopify Connection. One OAuth grant maps to one store, so the
1611
- * stable per-call selector is the store's myshopify domain (`shopDomain`),
1612
- * NOT `accountIdentifier` — the connect provider keys `accountIdentifier` on
1613
- * the immutable shop GID (falling back to the domain), so `shopDomain` is the
1614
- * value the LLM passes and the plugin routes on.
1615
- *
1616
- * Each entry is shaped by the connect provider's `buildCredentialsResponse`:
1617
- * `{ accessToken, shopDomain, shopGid, shopName, apiVersion }` — offline
1618
- * Shopify tokens never expire, so there is NO token / expiry field and no
1619
- * refresh method (unlike Salesforce). The GraphQL Admin API authenticates
1620
- * purely on `X-Shopify-Access-Token`; no client credentials are on the wire.
1621
- */
1622
- getShopifyAccounts(): Promise<{
1623
- accounts: {
1624
- connectionId: string;
1625
- accountIdentifier: string;
1626
- displayName: string | null;
1627
- connectedAt: string;
1628
- accessToken: string;
1629
- shopDomain: string;
1630
- shopGid: string;
1631
- shopName: string;
1632
- apiVersion: string;
1544
+ unmergeIdentity(identityId: string): Promise<{
1545
+ ok: boolean;
1546
+ error?: string;
1547
+ }>;
1548
+ addIdentityNote(identityId: string, args: {
1549
+ content: string;
1550
+ category?: string;
1551
+ }): Promise<{
1552
+ noteId: string | null;
1553
+ }>;
1554
+ tagIdentity(identityId: string, args: {
1555
+ tag: string;
1556
+ action: "add" | "remove";
1557
+ }): Promise<{
1558
+ ok: boolean;
1559
+ }>;
1560
+ getIdentityChangelog(identityId: string, args?: {
1561
+ limit?: number;
1562
+ cursor?: string;
1563
+ }): Promise<{
1564
+ entries: unknown[];
1565
+ cursor: string | null;
1566
+ }>;
1567
+ rollbackIdentity(identityId: string, args: {
1568
+ targetVersion: number;
1569
+ }): Promise<{
1570
+ ok: boolean;
1571
+ entry?: unknown;
1572
+ }>;
1573
+ requestIdentityVerification(args: {
1574
+ claimedIdentityId: string;
1575
+ requestingIdentityId: string;
1576
+ requestingProvider: string;
1577
+ requestingPlatformId: string;
1578
+ preferredChannel?: "mobile" | "email";
1579
+ /**
1580
+ * Phase 2: agent-supplied contact endpoint. When provided, the top-level
1581
+ * `preferredChannel` is ignored — the contact's channel wins.
1582
+ */
1583
+ contact?: {
1584
+ channel: "email" | "mobile";
1585
+ value: string;
1586
+ };
1587
+ }): Promise<{
1588
+ verificationId: string;
1589
+ channel: string;
1590
+ deliveredTo: string;
1591
+ expiresAt: string;
1592
+ availableChannels: {
1593
+ channel: string;
1594
+ deliveredTo: string;
1633
1595
  }[];
1596
+ } | {
1597
+ error: string;
1598
+ }>;
1599
+ confirmIdentityVerification(args: {
1600
+ claimedIdentityId: string;
1601
+ verificationId: string;
1602
+ phrase: string;
1603
+ }): Promise<{
1604
+ verified: boolean;
1605
+ identityId?: string;
1606
+ /** Phase 2: how the confirm resolved — Scenario A vs B. */
1607
+ action?: "merged" | "contact_verified" | "already_confirmed";
1608
+ error?: string;
1634
1609
  }>;
1635
1610
  /**
1636
- * Pattern A: provider-parameterized multi-account credential fetch for the
1637
- * social connectors (Bluesky, and the approval-gated backlog: X, Meta,
1638
- * Threads, LinkedIn, Pinterest, TikTok, Reddit, YouTube).
1639
- *
1640
- * Unlike the bespoke `getGithubAccounts()` / `getXeroAccounts()` shapes,
1641
- * this returns a UNIFORM normalized account shape so `@alfe.ai/social-mcp`'s
1642
- * shared driver can require a single `account` selector on every
1643
- * credential-touching tool regardless of platform. The backend
1644
- * `api-agents/{provider}/accounts` route is already provider-generic; this
1645
- * is the client-side normalization the plan (`do-we-need-any-moonlit-toucan`
1646
- * Phase 0, step 5) calls for.
1647
- *
1648
- * `accountIdentifier` is the stable per-account selector the LLM should
1649
- * pass back (for Bluesky: the account DID). `accessToken` carries whatever
1650
- * the provider's `buildCredentialsResponse` bundles (for Bluesky: the JSON
1651
- * session bundle — the driver parses the `accessJwt` out of it, or reads the
1652
- * top-level `accessJwt` from `providerMetadata`-adjacent fields). Everything
1653
- * else the driver needs for routing (handle, pdsHost, did, …) is on
1654
- * `providerMetadata`.
1655
- *
1656
- * Token refresh is delegated to connect (never done in-plugin) via the
1657
- * per-account route `POST /agent/connect/{provider}/accounts/{accountIdentifier}/refresh`
1658
- * — call `refreshSocialAccount(provider, accountIdentifier)`. (The non-account
1659
- * `POST /agent/connect/{provider}/refresh` route refreshes the provider's
1660
- * PRIMARY connection, which is wrong under multi-account Pattern A.)
1611
+ * Update display-shape fields on an Identity. Body excludes `email` /
1612
+ * `phone` / `title` / `company` / `metadata` per Section D4 — contacts go
1613
+ * via the verify flow, title/company live on OrgMembership, metadata is
1614
+ * not agent-writable.
1661
1615
  */
1662
- getSocialAccounts(provider: string): Promise<{
1663
- provider: string;
1664
- accounts: {
1665
- connectionId: string;
1666
- accountIdentifier: string;
1667
- displayName: string | null;
1668
- accessToken: string;
1669
- providerMetadata: Record<string, unknown>;
1670
- connectedAt: string;
1671
- }[];
1616
+ updateIdentity(identityId: string, args: {
1617
+ name?: string;
1618
+ avatarUrl?: string;
1619
+ timezone?: string;
1620
+ locale?: string;
1621
+ }): Promise<{
1622
+ ok: boolean;
1672
1623
  }>;
1673
1624
  /**
1674
- * Pattern A: refresh a specific social Connection by its stable
1675
- * `accountIdentifier` (for Bluesky: the account DID) via the
1676
- * provider-generic per-account refresh route. The counterpart to
1677
- * `getSocialAccounts(provider)`; `@alfe.ai/social-mcp` calls this on a
1678
- * 401/ExpiredToken from the platform PDS/API, then re-fetches accounts to
1679
- * pick up the rotated bundle.
1680
- *
1681
- * Refresh itself is ALWAYS delegated to connect — the plugin never calls
1682
- * the platform's own refresh XRPC (e.g. `com.atproto.server.refreshSession`)
1683
- * because connect owns the encrypted refresh token + rotation persistence
1684
- * (Bluesky rotates the refreshJwt; a missed rotation kills the connection
1685
- * after one refresh). The returned `accessToken` is whatever the provider's
1686
- * `refreshToken` hook re-bundled (for Bluesky: the JSON session bundle with
1687
- * the fresh `accessJwt`) — callers typically ignore it and re-fetch via
1688
- * `getSocialAccounts` for a consistent shape.
1625
+ * Phase 2 (Section H): server-side verification of a Google Chat sender via
1626
+ * the agent's existing Google OAuth credentials. Returns the resolved
1627
+ * identity (created or matched via Scenario-B email enrichment).
1689
1628
  */
1690
- refreshSocialAccount(provider: string, accountIdentifier: string): Promise<{
1691
- accountIdentifier: string;
1692
- accessToken: string;
1693
- accessTokenExpiresAt: string;
1694
- expiresAt: string;
1629
+ resolveGoogleChatSender(args: {
1630
+ senderUserId: string;
1631
+ spaceId?: string;
1632
+ }): Promise<{
1633
+ identityId: string | null;
1634
+ status: string;
1695
1635
  }>;
1696
1636
  }
1697
- //# sourceMappingURL=connect-credentials.d.ts.map
1637
+ //# sourceMappingURL=identity.d.ts.map
1638
+ //#endregion
1639
+ //#region src/domains/search.d.ts
1640
+ /**
1641
+ * The broad-news providers behind the metered `services/news` Lambda. The
1642
+ * server validates this with a zod enum; a value outside the union is an
1643
+ * unpriceable product, so keep the literal union in lockstep with the service.
1644
+ */
1645
+ type NewsProvider = "apitube" | "newsdata";
1646
+ /** One normalized article. `sentiment` is provider-shaped (APITube supplies it). */
1647
+ interface NewsArticle {
1648
+ title: string;
1649
+ url: string;
1650
+ source: string;
1651
+ publishedAt: string;
1652
+ snippet: string;
1653
+ sentiment?: unknown;
1654
+ }
1655
+ /** Provider-agnostic result — the server normalizes every adapter to this. */
1656
+ interface NewsResult {
1657
+ articles: NewsArticle[];
1658
+ provider: string;
1659
+ }
1660
+ declare class SearchApi extends ApiBase {
1661
+ searchWeb(params: {
1662
+ query: string;
1663
+ count?: number;
1664
+ offset?: number;
1665
+ country?: string;
1666
+ freshness?: string;
1667
+ }, options?: {
1668
+ signal?: AbortSignal;
1669
+ }): Promise<unknown>;
1670
+ searchImages(params: {
1671
+ query: string;
1672
+ count?: number;
1673
+ }, options?: {
1674
+ signal?: AbortSignal;
1675
+ }): Promise<unknown>;
1676
+ searchNews(params: {
1677
+ query: string;
1678
+ count?: number;
1679
+ offset?: number;
1680
+ freshness?: string;
1681
+ }, options?: {
1682
+ signal?: AbortSignal;
1683
+ }): Promise<unknown>;
1684
+ /** Search news across the selected provider's corpus. → POST /agent/news/search */
1685
+ newsSearch(params: {
1686
+ query: string;
1687
+ provider?: NewsProvider;
1688
+ source?: string;
1689
+ from?: string;
1690
+ to?: string;
1691
+ language?: string;
1692
+ category?: string;
1693
+ limit?: number;
1694
+ }): Promise<NewsResult>;
1695
+ /** Top headlines for the selected provider. → POST /agent/news/headlines */
1696
+ newsHeadlines(params?: {
1697
+ provider?: NewsProvider;
1698
+ category?: string;
1699
+ source?: string;
1700
+ language?: string;
1701
+ limit?: number;
1702
+ }): Promise<NewsResult>;
1703
+ }
1704
+ //# sourceMappingURL=search.d.ts.map
1705
+ //#endregion
1706
+ //#region src/domains/webhooks.d.ts
1707
+ interface AgentWebhook {
1708
+ webhookId: string;
1709
+ tenantId: string;
1710
+ agentId: string;
1711
+ name: string;
1712
+ provider: string;
1713
+ active: boolean;
1714
+ createdBy: string;
1715
+ createdAt: string;
1716
+ updatedAt: string;
1717
+ }
1718
+ interface CreatedAgentWebhook extends AgentWebhook {
1719
+ url: string;
1720
+ signingSecret: string;
1721
+ }
1722
+ interface AgentWebhookDelivery {
1723
+ deliveryId: string;
1724
+ webhookId: string;
1725
+ status: string;
1726
+ attempts: number;
1727
+ createdAt: string;
1728
+ deliveredAt?: string;
1729
+ }
1730
+ declare class WebhooksApi extends ApiBase {
1731
+ createWebhook(args: {
1732
+ name: string;
1733
+ provider?: "generic" | "github" | "stripe" | "slack";
1734
+ }): Promise<CreatedAgentWebhook>;
1735
+ listWebhooks(): Promise<AgentWebhook[]>;
1736
+ deleteWebhook(webhookId: string): Promise<{
1737
+ webhookId: string;
1738
+ active: false;
1739
+ }>;
1740
+ rotateWebhookSecret(webhookId: string): Promise<{
1741
+ webhookId: string;
1742
+ signingSecret: string;
1743
+ }>;
1744
+ listWebhookDeliveries(webhookId: string): Promise<AgentWebhookDelivery[]>;
1745
+ }
1746
+ //# sourceMappingURL=webhooks.d.ts.map
1747
+ //#endregion
1748
+ //#region src/domains/chat.d.ts
1749
+ declare class ChatApi extends ApiBase {
1750
+ ensureDirectConversation(identityId: string): Promise<{
1751
+ conversationId: string;
1752
+ identityId: string;
1753
+ tenantId: string;
1754
+ userId: string;
1755
+ displayName: string;
1756
+ created: boolean;
1757
+ }>;
1758
+ presignAttachments(files: {
1759
+ filename: string;
1760
+ mimeType: string;
1761
+ size: number;
1762
+ }[]): Promise<{
1763
+ attachments: {
1764
+ id: string;
1765
+ uploadUrl: string;
1766
+ uploadHeaders: Record<string, string>;
1767
+ downloadUrl: string;
1768
+ s3Key: string;
1769
+ expiresAt: string;
1770
+ }[];
1771
+ }>;
1772
+ recordActivity(data: {
1773
+ userId?: string;
1774
+ channel: string;
1775
+ role: "user" | "assistant";
1776
+ }): Promise<{
1777
+ recorded: boolean;
1778
+ }>;
1779
+ }
1780
+ //# sourceMappingURL=chat.d.ts.map
1698
1781
  //#endregion
1699
1782
  //#region src/domains/database.d.ts
1700
1783
  declare class DatabaseApi extends ApiBase {
@@ -1738,34 +1821,6 @@ declare class ImagesApi extends ApiBase {
1738
1821
  }
1739
1822
  //# sourceMappingURL=images.d.ts.map
1740
1823
  //#endregion
1741
- //#region src/domains/integrations.d.ts
1742
- declare class IntegrationsApi extends ApiBase {
1743
- listIntegrations(): Promise<IntegrationInstall[]>;
1744
- getIntegrationConfig(integrationId: string): Promise<IntegrationConfigResult>;
1745
- updateIntegrationConfig(integrationId: string, config: Record<string, unknown>): Promise<void>;
1746
- installIntegration(integrationId: string, options?: {
1747
- version?: string;
1748
- config?: Record<string, unknown>;
1749
- }): Promise<IntegrationInstall>;
1750
- removeIntegration(integrationId: string): Promise<IntegrationInstall>;
1751
- getOAuthUrl(provider: string, scopes?: string[], options?: {
1752
- shop?: string;
1753
- }): Promise<{
1754
- url: string;
1755
- provider: string;
1756
- expiresIn: number;
1757
- }>;
1758
- getOAuthStatus(provider: string): Promise<{
1759
- provider: string;
1760
- connected: boolean;
1761
- config?: Record<string, string>;
1762
- }>;
1763
- getRegistry(): Promise<{
1764
- integrations: RegistryEntry[];
1765
- }>;
1766
- }
1767
- //# sourceMappingURL=integrations.d.ts.map
1768
- //#endregion
1769
1824
  //#region src/domains/memory.d.ts
1770
1825
  declare class MemoryApi extends ApiBase {
1771
1826
  memorySearch(query: string, opts?: {