@alfe.ai/microsoft-mcp 0.1.13 → 0.1.14

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