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