@alfe.ai/mcp-server 0.2.10 → 0.2.12

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