@alfe.ai/mcp-server 0.2.4 → 0.2.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -1,44 +1,122 @@
1
1
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { Transport } from "@modelcontextprotocol/sdk/shared/transport.js";
2
3
  import { ChangelogEntry, EncryptedEnvelopeV1, FieldEnvelope, FieldFormat, FieldSensitivity, GeneratedDataKey, IntegrationConfigResult, IntegrationInstall, RegistryEntry, ScopeInfo, SecretAggregate, SecretCategory, SecretMetadata, SecretScope } from "@alfe/types";
3
4
 
4
5
  //#region ../agent-api-client/dist/index.d.ts
5
6
 
6
7
  //# sourceMappingURL=tool-error-capture.d.ts.map
7
8
  //#endregion
8
- //#region src/index.d.ts
9
+ //#region src/transport.d.ts
10
+ /**
11
+ * Shared HTTP transport for the Agent API client — request core, retry
12
+ * policy, error formatting, and the `ApiBase` class the domain method
13
+ * groups under `./domains/` build on.
14
+ */
9
15
  interface AgentApiClientConfig {
10
16
  apiKey: string;
11
17
  apiUrl: string;
12
18
  }
13
19
  /**
14
- * The broad-news providers behind the metered `services/news` Lambda. The
15
- * server validates this with a zod enum; a value outside the union is an
16
- * unpriceable product, so keep the literal union in lockstep with the service.
20
+ * Encode each path segment but keep the `/` separators — `encodeURIComponent`
21
+ * would escape the slashes too, breaking greedy proxy routes.
17
22
  */
18
- type NewsProvider = "apitube" | "newsdata";
19
- /** One normalized article. `sentiment` is provider-shaped (APITube supplies it). */
20
- interface NewsArticle {
21
- title: string;
22
- url: string;
23
- source: string;
24
- publishedAt: string;
25
- snippet: string;
26
- sentiment?: unknown;
23
+
24
+ declare class AgentApiTransport {
25
+ private readonly apiKey;
26
+ private readonly apiUrl;
27
+ constructor(config: AgentApiClientConfig);
28
+ /**
29
+ * Binary sibling of `request<T>()`. `request()` forces
30
+ * `Content-Type: application/json` and parses a `{ data: T }` envelope,
31
+ * neither of which fits a raw-audio flow (voice TTS/STT), so those go
32
+ * through this instead. Auth (Bearer), the request budget, and the single
33
+ * retry policy on transient 5xx / network errors is kept in sync with
34
+ * `request()`. Safe read methods retry once by default; mutation methods do
35
+ * not, because a response can be lost after a handler or provider call has
36
+ * already succeeded.
37
+ */
38
+ rawRequest(path: string, init: {
39
+ method: string;
40
+ headers: Headers;
41
+ body?: BodyInit | Uint8Array;
42
+ }, extra?: {
43
+ retry?: boolean;
44
+ }): Promise<Response>;
45
+ /**
46
+ * @param extra.timeoutMs Per-request abort timeout (default REQUEST_TIMEOUT_MS).
47
+ * Long endpoints (image generation) pass a larger value so the gateway's
48
+ * own timeout wins with a readable status instead of a client-side abort.
49
+ * @param extra.retry Whether to retry once on transient failures. Safe reads
50
+ * (GET/HEAD/OPTIONS) default to true; mutations default to false. Set true
51
+ * only when the endpoint's server-side contract is explicitly idempotent.
52
+ * @param extra.signal Optional caller cancellation combined with the client's
53
+ * own timeout budget. Aborting either signal cancels the request.
54
+ */
55
+ request<T>(path: string, options?: RequestInit, extra?: {
56
+ timeoutMs?: number;
57
+ retry?: boolean;
58
+ signal?: AbortSignal;
59
+ }): Promise<T>;
27
60
  }
28
- /** Provider-agnostic result — the server normalizes every adapter to this. */
29
- interface NewsResult {
30
- articles: NewsArticle[];
31
- provider: string;
61
+ /**
62
+ * Base class for the domain method groups. Holds the shared transport;
63
+ * `AgentApiClient` assembles the groups onto one class via `applyMixins`
64
+ * (prototype copy), so methods keep their original `this`-on-the-client
65
+ * call shape.
66
+ */
67
+ declare class ApiBase {
68
+ protected readonly transport: AgentApiTransport;
69
+ constructor(transport: AgentApiTransport);
32
70
  }
33
- interface RemoteSessionInfo {
34
- sessionId: string;
35
- agentId: string;
36
- surface: "browser" | "terminal";
37
- status: "agent_driving" | "awaiting_human" | "human_in_control" | "resuming" | "completed" | "expired" | "failed";
38
- url?: string;
39
- instructions?: string;
40
- requestedAt?: string;
71
+ //# sourceMappingURL=transport.d.ts.map
72
+ //#endregion
73
+ //#region src/domains/workspace.d.ts
74
+ /** Response of GET /agent/workspace (services/agents). */
75
+ interface AgentWorkspaceInfo {
76
+ templateKey?: string;
77
+ defaultModel?: string;
78
+ installedFrom?: {
79
+ templateKey: string;
80
+ authorTenantId: string;
81
+ version: number;
82
+ };
83
+ runtime?: string;
84
+ teams?: {
85
+ teamId: string;
86
+ name: string;
87
+ description?: string;
88
+ parentTeamId?: string;
89
+ }[];
90
+ projects?: {
91
+ projectId: string;
92
+ name: string;
93
+ description?: string;
94
+ status: string;
95
+ parentProjectId?: string;
96
+ }[];
97
+ teamIds?: string[];
98
+ projectIds?: string[];
99
+ }
100
+ declare class WorkspaceApi extends ApiBase {
101
+ /**
102
+ * GET /agent/workspace — workspace config for the authenticated agent
103
+ * (template assignment, default model, org roster).
104
+ */
105
+ getWorkspace(): Promise<AgentWorkspaceInfo>;
106
+ /**
107
+ * GET /templates/{key}/files — persona/workspace file contents for a
108
+ * template the agent has access to. Pass `version` to pin to the version
109
+ * the agent was installed from (omit → the endpoint resolves `latest`).
110
+ */
111
+ getTemplateFiles(templateKey: string, opts?: {
112
+ version?: number;
113
+ }): Promise<{
114
+ files: Record<string, string>;
115
+ }>;
41
116
  }
117
+ //# sourceMappingURL=workspace.d.ts.map
118
+ //#endregion
119
+ //#region src/domains/sync.d.ts
42
120
  interface SyncAgentInfo {
43
121
  agentId: string;
44
122
  tenantId: string;
@@ -123,6 +201,65 @@ interface SharedFileEntry {
123
201
  size: number;
124
202
  contentType?: string;
125
203
  }
204
+ declare class SyncApi extends ApiBase {
205
+ syncRegister(args?: {
206
+ displayName?: string;
207
+ }): Promise<{
208
+ agent: SyncAgentInfo;
209
+ }>;
210
+ syncGetManifest(): Promise<SyncManifest>;
211
+ syncPresign(args: {
212
+ files: {
213
+ path: string;
214
+ operation: "put" | "get";
215
+ contentType?: string;
216
+ }[];
217
+ }): Promise<{
218
+ urls: SyncPresignedUrl[];
219
+ }>;
220
+ syncConfirmUpload(args: {
221
+ filePath: string;
222
+ hash: string;
223
+ size: number;
224
+ storageClass?: "STANDARD" | "GLACIER_IR";
225
+ }): Promise<SyncConfirmedUpload>;
226
+ syncReconstruct(args: {
227
+ mode: "full" | "active" | "memory";
228
+ }): Promise<SyncReconstructBundle>;
229
+ syncGetStats(): Promise<SyncAgentStats>;
230
+ syncListFiles(args?: {
231
+ prefix?: string;
232
+ }): Promise<{
233
+ files: SyncFileEntry[];
234
+ }>;
235
+ syncListSessions(): Promise<{
236
+ sessions: SyncSessionEntry[];
237
+ }>;
238
+ syncGetSession(sessionId: string): Promise<SyncSessionContent>;
239
+ syncDeleteFile(filePath: string): Promise<{
240
+ removed: boolean;
241
+ }>;
242
+ sharedListFiles(args: {
243
+ scope: "org" | "team" | "project";
244
+ scopeId: string;
245
+ limit?: number;
246
+ cursor?: string;
247
+ }): Promise<{
248
+ files: SharedFileEntry[];
249
+ nextCursor: string | null;
250
+ }>;
251
+ sharedDownloadUrl(args: {
252
+ scope: "org" | "team" | "project";
253
+ scopeId: string;
254
+ filePath: string;
255
+ }): Promise<{
256
+ downloadUrl: string;
257
+ expiresIn: number;
258
+ }>;
259
+ }
260
+ //# sourceMappingURL=sync.d.ts.map
261
+ //#endregion
262
+ //#region src/domains/knowledge.d.ts
126
263
  type KnowledgeScopeType = "org" | "team" | "project";
127
264
  interface KnowledgeScope {
128
265
  scopeType: KnowledgeScopeType;
@@ -165,15 +302,6 @@ interface KnowledgeProfile {
165
302
  updatedAt: string | null;
166
303
  updatedBy: string | null;
167
304
  }
168
- interface KnowledgeDoc {
169
- filePath: string;
170
- fileName: string;
171
- contentType?: string;
172
- size: number;
173
- uploadedBy?: string;
174
- createdAt: string;
175
- updatedAt: string;
176
- }
177
305
  type ChangeRequestResourceType = "doc" | "profile";
178
306
  type ChangeRequestOperation = "create" | "update" | "delete";
179
307
  type ChangeRequestStatus = "open" | "approved" | "rejected" | "withdrawn" | "superseded";
@@ -215,6 +343,200 @@ interface ProposeScopeChangeInput {
215
343
  /** profile: the proposed value ({ about, description, links }). */
216
344
  proposedValue?: unknown;
217
345
  }
346
+ interface KnowledgeDoc {
347
+ filePath: string;
348
+ fileName: string;
349
+ contentType?: string;
350
+ size: number;
351
+ uploadedBy?: string;
352
+ createdAt: string;
353
+ updatedAt: string;
354
+ }
355
+ declare class KnowledgeApi extends ApiBase {
356
+ /**
357
+ * Semantic search across the agent's member scopes. Fan-out is gated
358
+ * server-side by `listScopes` set-inclusion (fail-closed). Pass
359
+ * `scopeType` + `scopeId` to narrow to one scope; a non-member scope
360
+ * yields empty results (never a cross-scope leak).
361
+ */
362
+ knowledgeSearch(query: string, opts?: {
363
+ limit?: number;
364
+ scopeType?: KnowledgeScopeType;
365
+ scopeId?: string;
366
+ }): Promise<KnowledgeSearchResult>;
367
+ /** Enumerate the scopes (org + teams + projects) this agent belongs to. */
368
+ listScopes(): Promise<{
369
+ scopes: KnowledgeScope[];
370
+ }>;
371
+ /** Read a scope's structured knowledge profile (after membership check). */
372
+ getScopeProfile(scopeType: KnowledgeScopeType, scopeId: string): Promise<KnowledgeProfile>;
373
+ /**
374
+ * Open a change request against a scope's knowledge resource. For a doc
375
+ * create/update, `services/org` returns a presigned staging PUT; this method
376
+ * uploads the proposed `content` to it (echoing the same Content-Type that
377
+ * was signed), mirroring `writeScopeDoc`. The staged body is applied to the
378
+ * canonical doc — attributed to this agent — only when a reviewer approves.
379
+ */
380
+ proposeScopeChange(scopeType: KnowledgeScopeType, scopeId: string, input: ProposeScopeChangeInput): Promise<KnowledgeChangeRequest>;
381
+ /**
382
+ * List the agent's OWN change requests in a scope (filtered server-side to
383
+ * this agent as proposer). Pass `status` to narrow to open / approved / etc.
384
+ */
385
+ listScopeChangeRequests(scopeType: KnowledgeScopeType, scopeId: string, opts?: {
386
+ status?: ChangeRequestStatus;
387
+ limit?: number;
388
+ cursor?: string;
389
+ }): Promise<{
390
+ changeRequests: KnowledgeChangeRequest[];
391
+ nextCursor: string | null;
392
+ }>;
393
+ /** List a scope's docs (the org-files corpus; mirrored to shared/<scope>/). */
394
+ listScopeDocs(scopeType: KnowledgeScopeType, scopeId: string, opts?: {
395
+ limit?: number;
396
+ cursor?: string;
397
+ }): Promise<{
398
+ files: KnowledgeDoc[];
399
+ nextCursor: string | null;
400
+ }>;
401
+ /**
402
+ * Read the full text of a scope doc. Resolves a presigned download URL
403
+ * from `services/org`, then fetches the bytes directly from S3 (the one
404
+ * legitimate raw fetch in a plugin — same pattern as sync).
405
+ */
406
+ readScopeDoc(scopeType: KnowledgeScopeType, scopeId: string, filePath: string, opts?: {
407
+ maxBytes?: number;
408
+ }): Promise<{
409
+ filePath: string;
410
+ text: string;
411
+ }>;
412
+ /**
413
+ * Write (create or overwrite) a scope doc. Two-step presigned upload:
414
+ * `services/org` returns a signed URL plus `requiredHeaders` (author /
415
+ * authorKind / message as `x-amz-meta-*`) that MUST be sent verbatim on
416
+ * the PUT, alongside the same `Content-Type` that was signed. Author and
417
+ * authorKind are server-set from the agent token — never trusted here.
418
+ */
419
+ writeScopeDoc(scopeType: KnowledgeScopeType, scopeId: string, filePath: string, content: string, opts?: {
420
+ contentType?: string;
421
+ message?: string;
422
+ }): Promise<{
423
+ filePath: string;
424
+ }>;
425
+ }
426
+ //# sourceMappingURL=knowledge.d.ts.map
427
+ //#endregion
428
+ //#region src/domains/mobile.d.ts
429
+ /** Response of GET /mobile/numbers for an agent (services/mobile). */
430
+ interface MobileNumberInfo {
431
+ phoneNumber: string;
432
+ countryCode: string;
433
+ monthlyPrice?: number;
434
+ status: string;
435
+ errorMessage?: string;
436
+ }
437
+ /** One purchasable number from GET /mobile/numbers/search. */
438
+ interface MobileAvailableNumber {
439
+ number: string;
440
+ friendlyName: string;
441
+ locality: string;
442
+ region: string;
443
+ country: string;
444
+ }
445
+ /** Approved WhatsApp content template from GET /mobile/whatsapp/templates. */
446
+ interface WhatsAppTemplate {
447
+ contentSid: string;
448
+ name: string;
449
+ language: string;
450
+ body: string;
451
+ variables: Record<string, string>;
452
+ category?: string;
453
+ }
454
+ declare class MobileApi extends ApiBase {
455
+ getMobileNumber(): Promise<MobileNumberInfo>;
456
+ searchMobileNumbers(args?: {
457
+ country?: string;
458
+ query?: string;
459
+ }): Promise<{
460
+ numbers: MobileAvailableNumber[];
461
+ monthlyPrice: number;
462
+ }>;
463
+ assignMobileNumber(args: {
464
+ phoneNumber: string;
465
+ countryCode: string;
466
+ }): Promise<{
467
+ phoneNumber: string;
468
+ countryCode: string;
469
+ status: "pending";
470
+ }>;
471
+ releaseMobileNumber(): Promise<{
472
+ released: true;
473
+ }>;
474
+ sendSms(args: {
475
+ to: string;
476
+ body: string;
477
+ }): Promise<{
478
+ sent: true;
479
+ sid: string;
480
+ }>;
481
+ startOutboundCall(args: {
482
+ to: string;
483
+ }): Promise<{
484
+ callSid: string;
485
+ status: string;
486
+ }>;
487
+ getWhatsAppSession(to: string): Promise<{
488
+ active: boolean;
489
+ expiresAt?: string;
490
+ }>;
491
+ sendWhatsAppMessage(args: {
492
+ to: string;
493
+ body: string;
494
+ }): Promise<{
495
+ sent: true;
496
+ sid: string;
497
+ }>;
498
+ sendWhatsAppTemplate(args: {
499
+ to: string;
500
+ contentSid: string;
501
+ contentVariables: Record<string, string>;
502
+ bodyPreview?: string;
503
+ }): Promise<{
504
+ sent: true;
505
+ sid: string;
506
+ }>;
507
+ listWhatsAppTemplates(): Promise<{
508
+ templates: WhatsAppTemplate[];
509
+ }>;
510
+ }
511
+ //# sourceMappingURL=mobile.d.ts.map
512
+ //#endregion
513
+ //#region src/domains/remote.d.ts
514
+ interface RemoteSessionInfo {
515
+ sessionId: string;
516
+ agentId: string;
517
+ surface: "browser" | "terminal";
518
+ status: "agent_driving" | "awaiting_human" | "human_in_control" | "resuming" | "completed" | "expired" | "failed";
519
+ url?: string;
520
+ instructions?: string;
521
+ requestedAt?: string;
522
+ }
523
+ declare class RemoteApi extends ApiBase {
524
+ requestBrowserTakeover(args: {
525
+ instructions: string;
526
+ url?: string;
527
+ conversationId?: string;
528
+ }): Promise<{
529
+ sessionId: string;
530
+ status: string;
531
+ }>;
532
+ getRemoteSession(sessionId: string): Promise<RemoteSessionInfo>;
533
+ completeRemoteSession(sessionId: string): Promise<{
534
+ ok: boolean;
535
+ }>;
536
+ }
537
+ //# sourceMappingURL=remote.d.ts.map
538
+ //#endregion
539
+ //#region src/domains/self.d.ts
218
540
  /** Voice settings — core agent config. Mirrors `VoiceConfig` in `@alfe/types`. */
219
541
  interface AgentVoiceConfig {
220
542
  /** ElevenLabs voice ID; platform default when unset. */
@@ -256,12 +578,51 @@ interface AgentVoice {
256
578
  labels: Record<string, string>;
257
579
  category: string;
258
580
  }
259
- /** The ElevenLabs models with a pricing row — the TTS endpoint rejects any other value. */
260
- type VoiceTtsModel = "eleven_turbo_v2_5" | "eleven_multilingual_v2";
261
- interface VoiceTtsArgs {
262
- /** Text to synthesize (1–5000 chars — the endpoint enforces this). */
263
- text: string;
264
- /** ElevenLabs voice id; platform default when unset. */
581
+ declare class SelfApi extends ApiBase {
582
+ /** Update the agent's own name and/or voice config. Returns the updated agent. */
583
+ updateSelf(update: {
584
+ name?: string;
585
+ voiceConfig?: AgentVoiceConfig;
586
+ }): Promise<AgentSelf>;
587
+ /**
588
+ * Generate the agent's own avatar from a text prompt. The image is generated,
589
+ * stored, and set on the agent server-side; returns the updated agent.
590
+ *
591
+ * ASYNC (same reason as `generateImage`): avatar gen runs `gpt-image-1`
592
+ * (30–60s) which exceeds the API Gateway 30s ceiling, so this enqueues a job
593
+ * (`POST /agent/avatar/generate` → `jobId`) then polls (`GET /agent/avatar/{jobId}`)
594
+ * until the avatar is set. Signature unchanged — the plugin is unaffected.
595
+ */
596
+ generateAvatar(args: {
597
+ prompt: string;
598
+ }): Promise<AgentSelf>;
599
+ /**
600
+ * Get a presigned PUT URL to upload a new avatar image. Upload the bytes to
601
+ * `uploadUrl`, then call `finalizeAvatar(s3Key)` to set it on the agent.
602
+ */
603
+ presignAvatar(args: {
604
+ mimeType: string;
605
+ size: number;
606
+ }): Promise<AgentAvatarPresign>;
607
+ /**
608
+ * Finalize an avatar upload — validates ownership + size, then sets the
609
+ * agent's `avatarUrl` server-side. Returns the updated agent.
610
+ */
611
+ finalizeAvatar(s3Key: string): Promise<AgentSelf>;
612
+ /** List the platform voice catalogue (ElevenLabs) so the agent can pick its own voice. */
613
+ listVoices(): Promise<{
614
+ voices: AgentVoice[];
615
+ }>;
616
+ }
617
+ //# sourceMappingURL=self.d.ts.map
618
+ //#endregion
619
+ //#region src/domains/voice.d.ts
620
+ /** The ElevenLabs models with a pricing row — the TTS endpoint rejects any other value. */
621
+ type VoiceTtsModel = "eleven_turbo_v2_5" | "eleven_multilingual_v2";
622
+ interface VoiceTtsArgs {
623
+ /** Text to synthesize (1–5000 chars — the endpoint enforces this). */
624
+ text: string;
625
+ /** ElevenLabs voice id; platform default when unset. */
265
626
  voiceId?: string;
266
627
  /** TTS model; `eleven_turbo_v2_5` (lower latency) when unset. */
267
628
  model?: VoiceTtsModel;
@@ -288,84 +649,161 @@ interface VoiceSttResult {
288
649
  /** Deepgram confidence in (0,1]. */
289
650
  confidence: number;
290
651
  }
291
- declare class AgentApiClient {
292
- private readonly apiKey;
293
- private readonly apiUrl;
294
- constructor(config: AgentApiClientConfig);
295
- private request;
296
- syncRegister(args?: {
297
- displayName?: string;
298
- }): Promise<{
299
- agent: SyncAgentInfo;
300
- }>;
301
- syncGetManifest(): Promise<SyncManifest>;
302
- syncPresign(args: {
303
- files: {
304
- path: string;
305
- operation: "put" | "get";
306
- contentType?: string;
307
- }[];
308
- }): Promise<{
309
- urls: SyncPresignedUrl[];
310
- }>;
311
- syncConfirmUpload(args: {
312
- filePath: string;
313
- hash: string;
652
+ declare class VoiceApi extends ApiBase {
653
+ /**
654
+ * Text-to-speech. Returns raw PCM audio bytes plus their framing — the
655
+ * voice service defaults to 24 kHz / mono / 16-bit. Wrap in a WAV container
656
+ * to produce a playable file. Metered per character against the tenant
657
+ * credit pool server-side; TTS completes regardless of metering outcome.
658
+ */
659
+ tts(args: VoiceTtsArgs): Promise<VoiceTtsResult>;
660
+ /**
661
+ * Speech-to-text. Accepts raw linear16 (16-bit LE) mono PCM — NOT a WAV or
662
+ * other container (the endpoint transcribes with a fixed linear16 encoding,
663
+ * so a container header would be transcribed as noise). Strip any WAV header
664
+ * and pass `sampleRate` from it before calling. Metered by transcribed
665
+ * duration against the tenant credit pool server-side.
666
+ */
667
+ stt(args: VoiceSttArgs): Promise<VoiceSttResult>;
668
+ }
669
+ //# sourceMappingURL=voice.d.ts.map
670
+ //#endregion
671
+ //#region src/domains/search.d.ts
672
+ /**
673
+ * The broad-news providers behind the metered `services/news` Lambda. The
674
+ * server validates this with a zod enum; a value outside the union is an
675
+ * unpriceable product, so keep the literal union in lockstep with the service.
676
+ */
677
+ type NewsProvider = "apitube" | "newsdata";
678
+ /** One normalized article. `sentiment` is provider-shaped (APITube supplies it). */
679
+ interface NewsArticle {
680
+ title: string;
681
+ url: string;
682
+ source: string;
683
+ publishedAt: string;
684
+ snippet: string;
685
+ sentiment?: unknown;
686
+ }
687
+ /** Provider-agnostic result — the server normalizes every adapter to this. */
688
+ interface NewsResult {
689
+ articles: NewsArticle[];
690
+ provider: string;
691
+ }
692
+ declare class SearchApi extends ApiBase {
693
+ searchWeb(params: {
694
+ query: string;
695
+ count?: number;
696
+ offset?: number;
697
+ country?: string;
698
+ freshness?: string;
699
+ }, options?: {
700
+ signal?: AbortSignal;
701
+ }): Promise<unknown>;
702
+ searchImages(params: {
703
+ query: string;
704
+ count?: number;
705
+ }, options?: {
706
+ signal?: AbortSignal;
707
+ }): Promise<unknown>;
708
+ searchNews(params: {
709
+ query: string;
710
+ count?: number;
711
+ offset?: number;
712
+ freshness?: string;
713
+ }, options?: {
714
+ signal?: AbortSignal;
715
+ }): Promise<unknown>;
716
+ /** Search news across the selected provider's corpus. → POST /agent/news/search */
717
+ newsSearch(params: {
718
+ query: string;
719
+ provider?: NewsProvider;
720
+ source?: string;
721
+ from?: string;
722
+ to?: string;
723
+ language?: string;
724
+ category?: string;
725
+ limit?: number;
726
+ }): Promise<NewsResult>;
727
+ /** Top headlines for the selected provider. → POST /agent/news/headlines */
728
+ newsHeadlines(params?: {
729
+ provider?: NewsProvider;
730
+ category?: string;
731
+ source?: string;
732
+ language?: string;
733
+ limit?: number;
734
+ }): Promise<NewsResult>;
735
+ }
736
+ //# sourceMappingURL=search.d.ts.map
737
+ //#endregion
738
+ //#region src/domains/webhooks.d.ts
739
+ interface AgentWebhook {
740
+ webhookId: string;
741
+ tenantId: string;
742
+ agentId: string;
743
+ name: string;
744
+ provider: string;
745
+ active: boolean;
746
+ createdBy: string;
747
+ createdAt: string;
748
+ updatedAt: string;
749
+ }
750
+ interface CreatedAgentWebhook extends AgentWebhook {
751
+ url: string;
752
+ signingSecret: string;
753
+ }
754
+ interface AgentWebhookDelivery {
755
+ deliveryId: string;
756
+ webhookId: string;
757
+ status: string;
758
+ attempts: number;
759
+ createdAt: string;
760
+ deliveredAt?: string;
761
+ }
762
+ declare class WebhooksApi extends ApiBase {
763
+ createWebhook(args: {
764
+ name: string;
765
+ provider?: "generic" | "github" | "stripe" | "slack";
766
+ }): Promise<CreatedAgentWebhook>;
767
+ listWebhooks(): Promise<AgentWebhook[]>;
768
+ deleteWebhook(webhookId: string): Promise<{
769
+ webhookId: string;
770
+ active: false;
771
+ }>;
772
+ rotateWebhookSecret(webhookId: string): Promise<{
773
+ webhookId: string;
774
+ signingSecret: string;
775
+ }>;
776
+ listWebhookDeliveries(webhookId: string): Promise<AgentWebhookDelivery[]>;
777
+ }
778
+ //# sourceMappingURL=webhooks.d.ts.map
779
+ //#endregion
780
+ //#region src/domains/chat.d.ts
781
+ declare class ChatApi extends ApiBase {
782
+ presignAttachments(files: {
783
+ filename: string;
784
+ mimeType: string;
314
785
  size: number;
315
- storageClass?: "STANDARD" | "GLACIER_IR";
316
- }): Promise<SyncConfirmedUpload>;
317
- syncReconstruct(args: {
318
- mode: "full" | "active" | "memory";
319
- }): Promise<SyncReconstructBundle>;
320
- syncGetStats(): Promise<SyncAgentStats>;
321
- syncListFiles(args?: {
322
- prefix?: string;
323
- }): Promise<{
324
- files: SyncFileEntry[];
325
- }>;
326
- syncListSessions(): Promise<{
327
- sessions: SyncSessionEntry[];
328
- }>;
329
- syncGetSession(sessionId: string): Promise<SyncSessionContent>;
330
- syncDeleteFile(filePath: string): Promise<{
331
- removed: boolean;
332
- }>;
333
- sharedListFiles(args: {
334
- scope: "org" | "team" | "project";
335
- scopeId: string;
336
- }): Promise<{
337
- files: SharedFileEntry[];
338
- nextCursor: string | null;
786
+ }[]): Promise<{
787
+ attachments: {
788
+ id: string;
789
+ uploadUrl: string;
790
+ downloadUrl: string;
791
+ s3Key: string;
792
+ expiresAt: string;
793
+ }[];
339
794
  }>;
340
- sharedDownloadUrl(args: {
341
- scope: "org" | "team" | "project";
342
- scopeId: string;
343
- filePath: string;
795
+ recordActivity(data: {
796
+ userId?: string;
797
+ channel: string;
798
+ role: "user" | "assistant";
344
799
  }): Promise<{
345
- downloadUrl: string;
346
- expiresIn: number;
347
- }>;
348
- listIntegrations(): Promise<IntegrationInstall[]>;
349
- getIntegrationConfig(integrationId: string): Promise<IntegrationConfigResult>;
350
- updateIntegrationConfig(integrationId: string, config: Record<string, unknown>): Promise<void>;
351
- installIntegration(integrationId: string, options?: {
352
- version?: string;
353
- config?: Record<string, unknown>;
354
- }): Promise<IntegrationInstall>;
355
- removeIntegration(integrationId: string): Promise<IntegrationInstall>;
356
- getOAuthUrl(provider: string, scopes?: string[]): Promise<{
357
- url: string;
358
- provider: string;
359
- expiresIn: number;
360
- }>;
361
- getOAuthStatus(provider: string): Promise<{
362
- provider: string;
363
- connected: boolean;
364
- config?: Record<string, string>;
365
- }>;
366
- getRegistry(): Promise<{
367
- integrations: RegistryEntry[];
800
+ recorded: boolean;
368
801
  }>;
802
+ }
803
+ //# sourceMappingURL=chat.d.ts.map
804
+ //#endregion
805
+ //#region src/domains/connect-credentials.d.ts
806
+ declare class ConnectCredentialsApi extends ApiBase {
369
807
  /**
370
808
  * Returns every connected Google account for the agent. Multi-account by
371
809
  * design — the openclaw-google plugin requires the LLM to pass `email`
@@ -422,82 +860,19 @@ declare class AgentApiClient {
422
860
  [key: string]: unknown;
423
861
  }>;
424
862
  /**
425
- * Resolve the primary cTrader Connection's credentials for the calling
426
- * agent. Unlike most providers, the cTrader Open API needs app-level auth
427
- * (`clientId` + `clientSecret`) AND account auth (`accessToken` +
428
- * `accountId`) on the socket, so `@alfe.ai/ctrader-mcp` self-fetches the
429
- * full set here at startup (the atlassian/google pattern). `clientId` /
430
- * `clientSecret` are the SST-sourced global app credentials the connect
431
- * endpoint injects — they are never persisted on the connection. `host` is
432
- * the resolved TLS endpoint (`live.ctraderapi.com` / `demo.ctraderapi.com`)
433
- * derived from the selected account's live/demo flag.
863
+ * @deprecated Returns a single primary credential blob (legacy "pick-the-
864
+ * default-connection" shape). Use `getGithubAccounts()` for the multi-
865
+ * account shape required by Pattern A explicit selector args on every
866
+ * tool. Retained because the `@alfe.ai/github-mcp` proxy is the
867
+ * only consumer that knows about Pattern A; legacy env-interpolation
868
+ * callers will keep hitting `/credentials` until they move to the proxy.
434
869
  */
435
- getCTraderCredentials(): Promise<{
870
+ getGithubCredentials(): Promise<{
871
+ login: string;
436
872
  accessToken: string;
437
- refreshToken: string;
438
- accountId: string;
439
- host: string;
440
- clientId: string;
441
- clientSecret: string;
442
873
  }>;
443
874
  /**
444
- * Pattern A: multi-account credential fetch for cTrader.
445
- *
446
- * Unlike atlassian/salesforce (one Connection row per account/site), a
447
- * cTrader is MULTI-grant per agent: an agent may connect several distinct
448
- * cTrader logins, each its own Connection row keyed on `accountIdentifier =
449
- * ctid:<userId>` (Phase 1). This aggregates the *trading accounts* across
450
- * ALL of those Connection rows — each row contributes its `availableAccounts`
451
- * flattened, and every account carries ITS OWN grant's `accessToken` (the
452
- * token that authenticates that account against the cTrader Open API). One
453
- * OAuth grant still covers all accounts under that single login on one shared
454
- * token; only the `ctidTraderAccountId` and the protobuf socket `host` (live
455
- * vs demo) differ within a grant. Across grants the tokens differ, so the
456
- * token is now PER-ACCOUNT rather than hoisted to the top level.
457
- *
458
- * `host` per account is derived from the account's `isLive` flag
459
- * (`live.ctraderapi.com` / `demo.ctraderapi.com`) — the same mapping the
460
- * connect provider applies server-side when an account is auto-selected.
461
- *
462
- * `clientId` / `clientSecret` are the SST-sourced GLOBAL app credentials the
463
- * connect endpoint injects — identical across every Connection row (one
464
- * cTrader app), never persisted on a connection. We take them from the first
465
- * row that carries them.
466
- *
467
- * Accounts are deduped on `ctidTraderAccountId` first-wins: Spotware ids are
468
- * globally unique across logins, so a duplicate can only appear if the same
469
- * account somehow surfaced under two grants — first-wins keeps it
470
- * deterministic.
471
- *
472
- * `accounts` may be empty (no cTrader Connection at all), in which case we
473
- * return empty creds rather than throwing.
474
- */
475
- getCTraderAccounts(): Promise<{
476
- accounts: {
477
- ctidTraderAccountId: string;
478
- host: string;
479
- isLive: boolean;
480
- brokerName?: string;
481
- accountNumber?: string;
482
- accessToken: string;
483
- }[];
484
- clientId: string;
485
- clientSecret: string;
486
- }>;
487
- /**
488
- * @deprecated Returns a single primary credential blob (legacy "pick-the-
489
- * default-connection" shape). Use `getGithubAccounts()` for the multi-
490
- * account shape required by Pattern A — explicit selector args on every
491
- * tool. Retained because the `@alfe.ai/github-mcp` proxy is the
492
- * only consumer that knows about Pattern A; legacy env-interpolation
493
- * callers will keep hitting `/credentials` until they move to the proxy.
494
- */
495
- getGithubCredentials(): Promise<{
496
- login: string;
497
- accessToken: string;
498
- }>;
499
- /**
500
- * Pattern A: multi-account credential fetch for GitHub.
875
+ * Pattern A: multi-account credential fetch for GitHub.
501
876
  *
502
877
  * Returns every agent-scoped GitHub connection. The caller is expected
503
878
  * to require a `login` selector on every credential-touching tool and
@@ -521,67 +896,6 @@ declare class AgentApiClient {
521
896
  scopes: string;
522
897
  }[];
523
898
  }>;
524
- /**
525
- * Pattern A: provider-parameterized multi-account credential fetch for the
526
- * social connectors (Bluesky, and the approval-gated backlog: X, Meta,
527
- * Threads, LinkedIn, Pinterest, TikTok, Reddit, YouTube).
528
- *
529
- * Unlike the bespoke `getGithubAccounts()` / `getXeroAccounts()` shapes,
530
- * this returns a UNIFORM normalized account shape so `@alfe.ai/social-mcp`'s
531
- * shared driver can require a single `account` selector on every
532
- * credential-touching tool regardless of platform. The backend
533
- * `api-agents/{provider}/accounts` route is already provider-generic; this
534
- * is the client-side normalization the plan (`do-we-need-any-moonlit-toucan`
535
- * Phase 0, step 5) calls for.
536
- *
537
- * `accountIdentifier` is the stable per-account selector the LLM should
538
- * pass back (for Bluesky: the account DID). `accessToken` carries whatever
539
- * the provider's `buildCredentialsResponse` bundles (for Bluesky: the JSON
540
- * session bundle — the driver parses the `accessJwt` out of it, or reads the
541
- * top-level `accessJwt` from `providerMetadata`-adjacent fields). Everything
542
- * else the driver needs for routing (handle, pdsHost, did, …) is on
543
- * `providerMetadata`.
544
- *
545
- * Token refresh is delegated to connect (never done in-plugin) via the
546
- * per-account route `POST /agent/connect/{provider}/accounts/{accountIdentifier}/refresh`
547
- * — call `refreshSocialAccount(provider, accountIdentifier)`. (The non-account
548
- * `POST /agent/connect/{provider}/refresh` route refreshes the provider's
549
- * PRIMARY connection, which is wrong under multi-account Pattern A.)
550
- */
551
- getSocialAccounts(provider: string): Promise<{
552
- provider: string;
553
- accounts: {
554
- connectionId: string;
555
- accountIdentifier: string;
556
- displayName: string | null;
557
- accessToken: string;
558
- providerMetadata: Record<string, unknown>;
559
- connectedAt: string;
560
- }[];
561
- }>;
562
- /**
563
- * Pattern A: refresh a specific social Connection by its stable
564
- * `accountIdentifier` (for Bluesky: the account DID) via the
565
- * provider-generic per-account refresh route. The counterpart to
566
- * `getSocialAccounts(provider)`; `@alfe.ai/social-mcp` calls this on a
567
- * 401/ExpiredToken from the platform PDS/API, then re-fetches accounts to
568
- * pick up the rotated bundle.
569
- *
570
- * Refresh itself is ALWAYS delegated to connect — the plugin never calls
571
- * the platform's own refresh XRPC (e.g. `com.atproto.server.refreshSession`)
572
- * because connect owns the encrypted refresh token + rotation persistence
573
- * (Bluesky rotates the refreshJwt; a missed rotation kills the connection
574
- * after one refresh). The returned `accessToken` is whatever the provider's
575
- * `refreshToken` hook re-bundled (for Bluesky: the JSON session bundle with
576
- * the fresh `accessJwt`) — callers typically ignore it and re-fetch via
577
- * `getSocialAccounts` for a consistent shape.
578
- */
579
- refreshSocialAccount(provider: string, accountIdentifier: string): Promise<{
580
- accountIdentifier: string;
581
- accessToken: string;
582
- accessTokenExpiresAt: string;
583
- expiresAt: string;
584
- }>;
585
899
  /**
586
900
  * @deprecated Returns a single primary credential blob (legacy "pick-the-
587
901
  * default-connection" shape). Use `getXeroAccounts()` for the multi-
@@ -599,8 +913,9 @@ declare class AgentApiClient {
599
913
  * selector arg (e.g. `xeroTenantId`) on every credential-touching tool
600
914
  * and look up the matching account by that selector at dispatch time.
601
915
  *
602
- * Returned `accounts[i].accountIdentifier` is the Xero tenantId the
603
- * stable cross-session identifier the LLM should pass.
916
+ * `xeroTenantId` is the model-facing organisation selector. The separate
917
+ * `accountIdentifier` is the Connect persistence key used for refresh and
918
+ * may be an email; never substitute one for the other.
604
919
  */
605
920
  getXeroAccounts(): Promise<{
606
921
  accounts: {
@@ -618,12 +933,12 @@ declare class AgentApiClient {
618
933
  expiresAt: string;
619
934
  }>;
620
935
  /**
621
- * Pattern A: refresh a specific Xero connection by its `accountIdentifier`
622
- * (the Xero `tenantId`). The legacy `refreshXeroToken()` only refreshes
623
- * the *primary* connection, which is wrong for multi-tenant Xero where
624
- * each tenant has its own non-interchangeable access token.
936
+ * Refresh a specific Xero Connection by its exact `accountIdentifier` from
937
+ * `getXeroAccounts()`. Do not substitute `xeroTenantId`: current Xero OAuth
938
+ * rows may use the account email as their persistence key even when a sole
939
+ * organisation tenant ID is available in provider metadata.
625
940
  */
626
- refreshXeroAccountToken(xeroTenantId: string): Promise<{
941
+ refreshXeroAccountToken(accountIdentifier: string): Promise<{
627
942
  accessToken: string;
628
943
  accessTokenExpiresAt: string;
629
944
  expiresAt: string;
@@ -778,6 +1093,21 @@ declare class AgentApiClient {
778
1093
  accessToken: string;
779
1094
  expiresAt: string;
780
1095
  }>;
1096
+ /**
1097
+ * Pattern A: refresh one MYOB Connection by its stable
1098
+ * `accountIdentifier` (the MYOB business id returned by
1099
+ * `getMYOBAccounts()`).
1100
+ *
1101
+ * MYOB refresh tokens belong to individual Connection rows. A
1102
+ * multi-business client must use this method instead of refreshing the
1103
+ * primary Connection and copying that access token into every cached
1104
+ * business client.
1105
+ */
1106
+ refreshMYOBAccountToken(accountIdentifier: string): Promise<{
1107
+ accessToken: string;
1108
+ accessTokenExpiresAt: string;
1109
+ expiresAt: string;
1110
+ }>;
781
1111
  /**
782
1112
  * @deprecated Returns a single primary credential blob. Use
783
1113
  * `getSalesforceAccounts()` for the multi-account shape required by
@@ -817,67 +1147,6 @@ declare class AgentApiClient {
817
1147
  accessTokenExpiresAt: string;
818
1148
  expiresAt: string;
819
1149
  }>;
820
- /**
821
- * @deprecated Returns a single primary credential blob. Use
822
- * `getShopifyAccounts()` for the multi-account shape required by Pattern A
823
- * (`@alfe.ai/shopify-mcp` keys per-shop on the myshopify domain).
824
- */
825
- getShopifyCredentials(): Promise<{
826
- accessToken: string;
827
- shopDomain: string;
828
- shopGid: string;
829
- shopName: string;
830
- apiVersion: string;
831
- }>;
832
- /**
833
- * Pattern A: multi-account credential fetch for Shopify. Returns every
834
- * agent-scoped Shopify Connection. One OAuth grant maps to one store, so the
835
- * stable per-call selector is the store's myshopify domain (`shopDomain`),
836
- * NOT `accountIdentifier` — the connect provider keys `accountIdentifier` on
837
- * the immutable shop GID (falling back to the domain), so `shopDomain` is the
838
- * value the LLM passes and the plugin routes on.
839
- *
840
- * Each entry is shaped by the connect provider's `buildCredentialsResponse`:
841
- * `{ accessToken, shopDomain, shopGid, shopName, apiVersion }` — offline
842
- * Shopify tokens never expire, so there is NO token / expiry field and no
843
- * refresh method (unlike Salesforce). The GraphQL Admin API authenticates
844
- * purely on `X-Shopify-Access-Token`; no client credentials are on the wire.
845
- */
846
- getShopifyAccounts(): Promise<{
847
- accounts: {
848
- connectionId: string;
849
- accountIdentifier: string;
850
- displayName: string | null;
851
- connectedAt: string;
852
- accessToken: string;
853
- shopDomain: string;
854
- shopGid: string;
855
- shopName: string;
856
- apiVersion: string;
857
- }[];
858
- }>;
859
- /**
860
- * Disconnects one connected Microsoft 365 account for the agent, by its
861
- * `accountIdentifier`. Hits the generic per-account disconnect route
862
- * (`DELETE /agent/connect/microsoft/accounts/{accountIdentifier}`), which
863
- * resolves across the agent's full effective scope chain and deletes the
864
- * matching Connection row. Returns the remaining accounts.
865
- *
866
- * IMPORTANT: pass the `accountIdentifier` from `getMicrosoftAccounts()`, NOT
867
- * a synthesised email. For Microsoft, `accountIdentifier` is the user's email
868
- * only when the Graph profile fetch succeeded at connect time; it falls back
869
- * to the Azure tenant id (`tid` claim) otherwise. The backend matches on
870
- * `accountIdentifier` exactly, so passing an email would 404 on those
871
- * fallback-identifier accounts. (This is why the param is not named `email`,
872
- * unlike `disconnectGoogleAccount` where the identifier is always the email.)
873
- */
874
- disconnectMicrosoftAccount(accountIdentifier: string): Promise<{
875
- accounts: {
876
- accountIdentifier: string;
877
- displayName?: string;
878
- connectedAt?: string;
879
- }[];
880
- }>;
881
1150
  /**
882
1151
  * Pattern A: multi-account credential fetch for Microsoft 365.
883
1152
  *
@@ -901,9 +1170,6 @@ declare class AgentApiClient {
901
1170
  connectedAt: string;
902
1171
  accessToken: string;
903
1172
  accessTokenExpiresAt: string;
904
- refreshToken: string;
905
- clientId: string;
906
- clientSecret: string;
907
1173
  email: string;
908
1174
  microsoftTenantId: string;
909
1175
  workspaceDomain: string;
@@ -928,242 +1194,213 @@ declare class AgentApiClient {
928
1194
  accessTokenExpiresAt: string;
929
1195
  expiresAt: string;
930
1196
  }>;
931
- getTeamsCredentials(): Promise<{
932
- agentId: string;
933
- tenantId: string;
934
- azureAppId: string;
935
- azureBotId: string;
936
- azureClientSecret: string;
937
- botDisplayName?: string;
938
- teamsTenantId?: string;
939
- serviceUrl?: string;
940
- }>;
941
- sendTeamsMessage(data: {
942
- conversationId: string;
943
- text?: string;
944
- adaptiveCard?: Record<string, unknown>;
945
- }): Promise<{
946
- ok: boolean;
947
- activityId: string;
948
- }>;
949
- listTeamsChannels(): Promise<{
950
- channels: {
951
- id: string;
952
- name: string;
953
- description?: string;
954
- }[];
955
- }>;
956
- presignAttachments(files: {
957
- filename: string;
958
- mimeType: string;
959
- size: number;
960
- }[]): Promise<{
961
- attachments: {
962
- id: string;
963
- uploadUrl: string;
964
- downloadUrl: string;
965
- s3Key: string;
966
- expiresAt: string;
967
- }[];
968
- }>;
969
1197
  /**
970
- * Generate an image from a text prompt and get back a STABLE, public URL
971
- * (served from the agent-assets CDN — it does not expire). Embed the returned
972
- * `imageUrl` in a reply as markdown to show it to the user.
1198
+ * Disconnects one connected Microsoft 365 account for the agent, by its
1199
+ * `accountIdentifier`. Hits the generic per-account disconnect route
1200
+ * (`DELETE /agent/connect/microsoft/accounts/{accountIdentifier}`), which
1201
+ * resolves across the agent's full effective scope chain and deletes the
1202
+ * matching Connection row. Returns the remaining accounts.
973
1203
  *
974
- * ASYNC: `gpt-image-1` routinely runs 30–60s, which exceeds the API Gateway
975
- * 30s ceiling, so this enqueues a job (`POST /agent/images/generate`
976
- * `jobId`) then polls (`GET /agent/images/{jobId}`) until it completes. The
977
- * worker's real failure message (e.g. an unsupported `size`) surfaces via the
978
- * job's `error` field.
1204
+ * IMPORTANT: pass the `accountIdentifier` from `getMicrosoftAccounts()`, NOT
1205
+ * a synthesised email. For Microsoft, `accountIdentifier` is the user's email
1206
+ * only when the Graph profile fetch succeeded at connect time; it falls back
1207
+ * to the Azure tenant id (`tid` claim) otherwise. The backend matches on
1208
+ * `accountIdentifier` exactly, so passing an email would 404 on those
1209
+ * fallback-identifier accounts. (This is why the param is not named `email`,
1210
+ * unlike `disconnectGoogleAccount` where the identifier is always the email.)
979
1211
  */
980
- generateImage(args: {
981
- prompt: string;
982
- model?: string;
983
- size?: string;
984
- quality?: string;
985
- }): Promise<{
986
- imageUrl: string;
987
- model: string;
988
- }>;
989
- recordActivity(data: {
990
- userId?: string;
991
- channel: string;
992
- role: "user" | "assistant";
993
- }): Promise<{
994
- recorded: boolean;
1212
+ disconnectMicrosoftAccount(accountIdentifier: string): Promise<{
1213
+ accounts: {
1214
+ accountIdentifier: string;
1215
+ displayName?: string;
1216
+ connectedAt?: string;
1217
+ }[];
995
1218
  }>;
996
- /** Update the agent's own name and/or voice config. Returns the updated agent. */
997
- updateSelf(update: {
998
- name?: string;
999
- voiceConfig?: AgentVoiceConfig;
1000
- }): Promise<AgentSelf>;
1001
- /**
1002
- * Generate the agent's own avatar from a text prompt. The image is generated,
1003
- * stored, and set on the agent server-side; returns the updated agent.
1004
- *
1005
- * ASYNC (same reason as `generateImage`): avatar gen runs `gpt-image-1`
1006
- * (30–60s) which exceeds the API Gateway 30s ceiling, so this enqueues a job
1007
- * (`POST /agent/avatar/generate` → `jobId`) then polls (`GET /agent/avatar/{jobId}`)
1008
- * until the avatar is set. Signature unchanged — the plugin is unaffected.
1009
- */
1010
- generateAvatar(args: {
1011
- prompt: string;
1012
- }): Promise<AgentSelf>;
1013
- /**
1014
- * Get a presigned PUT URL to upload a new avatar image. Upload the bytes to
1015
- * `uploadUrl`, then call `finalizeAvatar(s3Key)` to set it on the agent.
1016
- */
1017
- presignAvatar(args: {
1018
- mimeType: string;
1019
- size: number;
1020
- }): Promise<AgentAvatarPresign>;
1021
1219
  /**
1022
- * Finalize an avatar upload validates ownership + size, then sets the
1023
- * agent's `avatarUrl` server-side. Returns the updated agent.
1220
+ * Resolve the primary cTrader Connection's credentials for the calling
1221
+ * agent. Unlike most providers, the cTrader Open API needs app-level auth
1222
+ * (`clientId` + `clientSecret`) AND account auth (`accessToken` +
1223
+ * `accountId`) on the socket, so `@alfe.ai/ctrader-mcp` self-fetches the
1224
+ * full set here at startup (the atlassian/google pattern). `clientId` /
1225
+ * `clientSecret` are the SST-sourced global app credentials the connect
1226
+ * endpoint injects — they are never persisted on the connection. `host` is
1227
+ * the resolved TLS endpoint (`live.ctraderapi.com` / `demo.ctraderapi.com`)
1228
+ * derived from the selected account's live/demo flag.
1024
1229
  */
1025
- finalizeAvatar(s3Key: string): Promise<AgentSelf>;
1026
- /** List the platform voice catalogue (ElevenLabs) so the agent can pick its own voice. */
1027
- listVoices(): Promise<{
1028
- voices: AgentVoice[];
1230
+ getCTraderCredentials(): Promise<{
1231
+ accessToken: string;
1232
+ refreshToken: string;
1233
+ accountId: string;
1234
+ host: string;
1235
+ clientId: string;
1236
+ clientSecret: string;
1029
1237
  }>;
1030
1238
  /**
1031
- * Mint a fresh AES-256 data key for a specific (secret, field) pair. The
1032
- * encryption context is rebuilt server-side from `auth.tenantId` + the body
1033
- * fields including `fieldKey`; the agent cannot forge context for a scope
1034
- * or field it doesn't own. Legacy single-envelope secrets are migrated to
1035
- * `field#value` rows by the data migration, so call with `fieldKey: "value"`
1036
- * to reach them.
1239
+ * Pattern A: multi-account credential fetch for cTrader.
1240
+ *
1241
+ * Unlike atlassian/salesforce (one Connection row per account/site), a
1242
+ * cTrader is MULTI-grant per agent: an agent may connect several distinct
1243
+ * cTrader logins, each its own Connection row keyed on `accountIdentifier =
1244
+ * ctid:<userId>` (Phase 1). This aggregates the *trading accounts* across
1245
+ * ALL of those Connection rows — each row contributes its `availableAccounts`
1246
+ * flattened, and every account carries ITS OWN grant's `accessToken` (the
1247
+ * token that authenticates that account against the cTrader Open API). One
1248
+ * OAuth grant still covers all accounts under that single login on one shared
1249
+ * token; only the `ctidTraderAccountId` and the protobuf socket `host` (live
1250
+ * vs demo) differ within a grant. Across grants the tokens differ, so the
1251
+ * token is now PER-ACCOUNT rather than hoisted to the top level.
1252
+ *
1253
+ * `host` per account is derived from the account's `isLive` flag
1254
+ * (`live.ctraderapi.com` / `demo.ctraderapi.com`) — the same mapping the
1255
+ * connect provider applies server-side when an account is auto-selected.
1256
+ *
1257
+ * `clientId` / `clientSecret` are the SST-sourced GLOBAL app credentials the
1258
+ * connect endpoint injects — identical across every Connection row (one
1259
+ * cTrader app), never persisted on a connection. We take them from the first
1260
+ * row that carries them.
1261
+ *
1262
+ * Accounts are deduped on `ctidTraderAccountId` first-wins: Spotware ids are
1263
+ * globally unique across logins, so a duplicate can only appear if the same
1264
+ * account somehow surfaced under two grants — first-wins keeps it
1265
+ * deterministic.
1266
+ *
1267
+ * `accounts` may be empty (no cTrader Connection at all), in which case we
1268
+ * return empty creds rather than throwing.
1037
1269
  */
1038
- generateSecretDataKey(args: {
1039
- scope: SecretScope;
1040
- scopeId: string;
1041
- secretId: string;
1042
- fieldKey: string;
1043
- }): Promise<GeneratedDataKey>;
1270
+ getCTraderAccounts(): Promise<{
1271
+ accounts: {
1272
+ ctidTraderAccountId: string;
1273
+ host: string;
1274
+ isLive: boolean;
1275
+ brokerName?: string;
1276
+ accountNumber?: string;
1277
+ accessToken: string;
1278
+ }[];
1279
+ clientId: string;
1280
+ clientSecret: string;
1281
+ }>;
1044
1282
  /**
1045
- * Unwrap a wrapped data key so the agent can decrypt the envelope locally.
1046
- * `fieldKey` MUST match the value supplied when the data key was generated
1047
- * (it's bound into KMS encryption context); mismatch fails with
1048
- * `InvalidCiphertextException`.
1283
+ * @deprecated Returns a single primary credential blob. Use
1284
+ * `getShopifyAccounts()` for the multi-account shape required by Pattern A
1285
+ * (`@alfe.ai/shopify-mcp` keys per-shop on the myshopify domain).
1049
1286
  */
1050
- decryptSecretDataKey(args: {
1051
- scope: SecretScope;
1052
- scopeId: string;
1053
- secretId: string;
1054
- fieldKey: string;
1055
- dataKeyCiphertext: string;
1056
- }): Promise<{
1057
- plaintextKey: string;
1287
+ getShopifyCredentials(): Promise<{
1288
+ accessToken: string;
1289
+ shopDomain: string;
1290
+ shopGid: string;
1291
+ shopName: string;
1292
+ apiVersion: string;
1058
1293
  }>;
1059
1294
  /**
1060
- * Create a new secret with one or more fields. Encrypted fields must arrive
1061
- * pre-sealed (the agent has already obtained per-field data keys via
1062
- * `generateSecretDataKey({ ..., fieldKey })` and AES-encrypted locally).
1063
- * Plaintext fields ship the value inline.
1295
+ * Pattern A: multi-account credential fetch for Shopify. Returns every
1296
+ * agent-scoped Shopify Connection. One OAuth grant maps to one store, so the
1297
+ * stable per-call selector is the store's myshopify domain (`shopDomain`),
1298
+ * NOT `accountIdentifier` the connect provider keys `accountIdentifier` on
1299
+ * the immutable shop GID (falling back to the domain), so `shopDomain` is the
1300
+ * value the LLM passes and the plugin routes on.
1301
+ *
1302
+ * Each entry is shaped by the connect provider's `buildCredentialsResponse`:
1303
+ * `{ accessToken, shopDomain, shopGid, shopName, apiVersion }` — offline
1304
+ * Shopify tokens never expire, so there is NO token / expiry field and no
1305
+ * refresh method (unlike Salesforce). The GraphQL Admin API authenticates
1306
+ * purely on `X-Shopify-Access-Token`; no client credentials are on the wire.
1064
1307
  */
1065
- createSecret(args: {
1066
- scope: SecretScope;
1067
- scopeId: string;
1068
- secretId: string;
1069
- secretName: string;
1070
- category?: SecretCategory;
1071
- description?: string;
1072
- tags?: string[];
1073
- fields: {
1074
- key: string;
1075
- format?: FieldFormat;
1076
- sensitivity: FieldSensitivity;
1077
- value?: string;
1078
- envelope?: EncryptedEnvelopeV1;
1308
+ getShopifyAccounts(): Promise<{
1309
+ accounts: {
1310
+ connectionId: string;
1311
+ accountIdentifier: string;
1312
+ displayName: string | null;
1313
+ connectedAt: string;
1314
+ accessToken: string;
1315
+ shopDomain: string;
1316
+ shopGid: string;
1317
+ shopName: string;
1318
+ apiVersion: string;
1079
1319
  }[];
1080
- reason?: string;
1081
- }): Promise<SecretAggregate>;
1082
- /** Fetch the secret aggregate plus per-field encrypted envelopes. */
1083
- getSecret(args: {
1084
- scope: SecretScope;
1085
- scopeId: string;
1086
- secretId: string;
1087
- }): Promise<{
1088
- aggregate: SecretAggregate;
1089
- envelopes: FieldEnvelope[];
1090
1320
  }>;
1091
- /** Fetch one field. Plaintext: value inline. Encrypted: envelope. */
1092
- getSecretField(args: {
1093
- scope: SecretScope;
1094
- scopeId: string;
1095
- secretId: string;
1096
- fieldKey: string;
1097
- }): Promise<{
1098
- key: string;
1099
- sensitivity: FieldSensitivity;
1100
- format?: FieldFormat;
1101
- value?: string;
1102
- envelope?: EncryptedEnvelopeV1;
1103
- rotatedAt?: string;
1104
- createdAt: string;
1105
- updatedAt: string;
1321
+ /**
1322
+ * Pattern A: provider-parameterized multi-account credential fetch for the
1323
+ * social connectors (Bluesky, and the approval-gated backlog: X, Meta,
1324
+ * Threads, LinkedIn, Pinterest, TikTok, Reddit, YouTube).
1325
+ *
1326
+ * Unlike the bespoke `getGithubAccounts()` / `getXeroAccounts()` shapes,
1327
+ * this returns a UNIFORM normalized account shape so `@alfe.ai/social-mcp`'s
1328
+ * shared driver can require a single `account` selector on every
1329
+ * credential-touching tool regardless of platform. The backend
1330
+ * `api-agents/{provider}/accounts` route is already provider-generic; this
1331
+ * is the client-side normalization the plan (`do-we-need-any-moonlit-toucan`
1332
+ * Phase 0, step 5) calls for.
1333
+ *
1334
+ * `accountIdentifier` is the stable per-account selector the LLM should
1335
+ * pass back (for Bluesky: the account DID). `accessToken` carries whatever
1336
+ * the provider's `buildCredentialsResponse` bundles (for Bluesky: the JSON
1337
+ * session bundle — the driver parses the `accessJwt` out of it, or reads the
1338
+ * top-level `accessJwt` from `providerMetadata`-adjacent fields). Everything
1339
+ * else the driver needs for routing (handle, pdsHost, did, …) is on
1340
+ * `providerMetadata`.
1341
+ *
1342
+ * Token refresh is delegated to connect (never done in-plugin) via the
1343
+ * per-account route `POST /agent/connect/{provider}/accounts/{accountIdentifier}/refresh`
1344
+ * — call `refreshSocialAccount(provider, accountIdentifier)`. (The non-account
1345
+ * `POST /agent/connect/{provider}/refresh` route refreshes the provider's
1346
+ * PRIMARY connection, which is wrong under multi-account Pattern A.)
1347
+ */
1348
+ getSocialAccounts(provider: string): Promise<{
1349
+ provider: string;
1350
+ accounts: {
1351
+ connectionId: string;
1352
+ accountIdentifier: string;
1353
+ displayName: string | null;
1354
+ accessToken: string;
1355
+ providerMetadata: Record<string, unknown>;
1356
+ connectedAt: string;
1357
+ }[];
1106
1358
  }>;
1107
- /** Add OR rotate one field. */
1108
- setSecretField(args: {
1109
- scope: SecretScope;
1110
- scopeId: string;
1111
- secretId: string;
1112
- fieldKey: string;
1113
- sensitivity: FieldSensitivity;
1114
- format?: FieldFormat;
1115
- value?: string;
1116
- envelope?: EncryptedEnvelopeV1;
1117
- reason?: string;
1118
- }): Promise<{
1119
- fieldKey: string;
1120
- rotated: boolean;
1359
+ /**
1360
+ * Pattern A: refresh a specific social Connection by its stable
1361
+ * `accountIdentifier` (for Bluesky: the account DID) via the
1362
+ * provider-generic per-account refresh route. The counterpart to
1363
+ * `getSocialAccounts(provider)`; `@alfe.ai/social-mcp` calls this on a
1364
+ * 401/ExpiredToken from the platform PDS/API, then re-fetches accounts to
1365
+ * pick up the rotated bundle.
1366
+ *
1367
+ * Refresh itself is ALWAYS delegated to connect — the plugin never calls
1368
+ * the platform's own refresh XRPC (e.g. `com.atproto.server.refreshSession`)
1369
+ * because connect owns the encrypted refresh token + rotation persistence
1370
+ * (Bluesky rotates the refreshJwt; a missed rotation kills the connection
1371
+ * after one refresh). The returned `accessToken` is whatever the provider's
1372
+ * `refreshToken` hook re-bundled (for Bluesky: the JSON session bundle with
1373
+ * the fresh `accessJwt`) — callers typically ignore it and re-fetch via
1374
+ * `getSocialAccounts` for a consistent shape.
1375
+ */
1376
+ refreshSocialAccount(provider: string, accountIdentifier: string): Promise<{
1377
+ accountIdentifier: string;
1378
+ accessToken: string;
1379
+ accessTokenExpiresAt: string;
1380
+ expiresAt: string;
1121
1381
  }>;
1122
- /** Remove one field. */
1123
- removeSecretField(args: {
1124
- scope: SecretScope;
1125
- scopeId: string;
1126
- secretId: string;
1127
- fieldKey: string;
1128
- }): Promise<void>;
1129
- /** Update secret-level metadata (name/description/tags/category). */
1130
- updateSecretMetadata(args: {
1131
- scope: SecretScope;
1132
- scopeId: string;
1133
- secretId: string;
1134
- secretName?: string;
1135
- description?: string;
1136
- tags?: string[];
1137
- category?: SecretCategory;
1138
- reason?: string;
1139
- }): Promise<SecretAggregate>;
1140
- /** List metadata for secrets in a scope. Optional filters route through the byFacet GSI. */
1141
- listSecrets(args: {
1142
- scope: SecretScope;
1143
- scopeId: string;
1144
- category?: SecretCategory;
1145
- tag?: string;
1146
- fieldKey?: string;
1147
- }): Promise<SecretMetadata[]>;
1148
- /** Bounded changelog read — metadata-only audit entries. */
1149
- getSecretHistory(args: {
1150
- scope: SecretScope;
1151
- scopeId: string;
1152
- secretId: string;
1153
- limit?: number;
1154
- cursor?: string;
1155
- }): Promise<{
1156
- entries: ChangelogEntry[];
1157
- nextCursor?: string;
1382
+ }
1383
+ //# sourceMappingURL=connect-credentials.d.ts.map
1384
+ //#endregion
1385
+ //#region src/domains/database.d.ts
1386
+ declare class DatabaseApi extends ApiBase {
1387
+ registerDatabaseCredentials(): Promise<{
1388
+ connectionString: string;
1389
+ username: string;
1390
+ password: string;
1391
+ databases: string[];
1158
1392
  }>;
1159
- /** Delete a secret (and all its field rows + tag rows + changelog rows). */
1160
- deleteSecret(args: {
1161
- scope: SecretScope;
1162
- scopeId: string;
1163
- secretId: string;
1393
+ reportDatabaseAudit(entry: {
1394
+ database: string;
1395
+ collection: string;
1396
+ operation: string;
1397
+ summary?: string;
1164
1398
  }): Promise<void>;
1165
- /** Enumerate scopes (org/team/project/agent) this agent can access. */
1166
- listSecretScopes(): Promise<ScopeInfo[]>;
1399
+ }
1400
+ //# sourceMappingURL=database.d.ts.map
1401
+ //#endregion
1402
+ //#region src/domains/identity.d.ts
1403
+ declare class IdentityApi extends ApiBase {
1167
1404
  /**
1168
1405
  * Returns the calling agent's own identity context — `{ agentId, tenantId }`
1169
1406
  * decoded server-side from the agent API token. Used by the
@@ -1206,59 +1443,35 @@ declare class AgentApiClient {
1206
1443
  }>;
1207
1444
  mergeIdentities(survivorId: string, args: {
1208
1445
  mergedId: string;
1209
- changedBy: {
1210
- type: string;
1211
- id: string;
1212
- name?: string;
1213
- };
1214
1446
  }): Promise<{
1215
1447
  ok: boolean;
1216
1448
  error?: string;
1217
1449
  }>;
1218
- unmergeIdentity(identityId: string, args: {
1219
- changedBy: {
1220
- type: string;
1221
- id: string;
1222
- name?: string;
1223
- };
1224
- }): Promise<{
1450
+ unmergeIdentity(identityId: string): Promise<{
1225
1451
  ok: boolean;
1226
1452
  error?: string;
1227
1453
  }>;
1228
1454
  addIdentityNote(identityId: string, args: {
1229
1455
  content: string;
1230
1456
  category?: string;
1231
- changedBy: {
1232
- type: string;
1233
- id: string;
1234
- name?: string;
1235
- };
1236
1457
  }): Promise<{
1237
1458
  noteId: string | null;
1238
1459
  }>;
1239
1460
  tagIdentity(identityId: string, args: {
1240
1461
  tag: string;
1241
1462
  action: "add" | "remove";
1242
- changedBy: {
1243
- type: string;
1244
- id: string;
1245
- name?: string;
1246
- };
1247
1463
  }): Promise<{
1248
1464
  ok: boolean;
1249
1465
  }>;
1250
1466
  getIdentityChangelog(identityId: string, args?: {
1251
1467
  limit?: number;
1468
+ cursor?: string;
1252
1469
  }): Promise<{
1253
1470
  entries: unknown[];
1471
+ cursor: string | null;
1254
1472
  }>;
1255
1473
  rollbackIdentity(identityId: string, args: {
1256
1474
  targetVersion: number;
1257
- changedBy: {
1258
- type: string;
1259
- id: string;
1260
- name?: string;
1261
- };
1262
1475
  }): Promise<{
1263
1476
  ok: boolean;
1264
1477
  entry?: unknown;
@@ -1297,7 +1510,7 @@ declare class AgentApiClient {
1297
1510
  verified: boolean;
1298
1511
  identityId?: string;
1299
1512
  /** Phase 2: how the confirm resolved — Scenario A vs B. */
1300
- action?: "merged" | "contact_verified";
1513
+ action?: "merged" | "contact_verified" | "already_confirmed";
1301
1514
  error?: string;
1302
1515
  }>;
1303
1516
  /**
@@ -1326,6 +1539,62 @@ declare class AgentApiClient {
1326
1539
  identityId: string | null;
1327
1540
  status: string;
1328
1541
  }>;
1542
+ }
1543
+ //# sourceMappingURL=identity.d.ts.map
1544
+ //#endregion
1545
+ //#region src/domains/images.d.ts
1546
+ declare class ImagesApi extends ApiBase {
1547
+ /**
1548
+ * Generate an image from a text prompt and get back a STABLE, public URL
1549
+ * (served from the agent-assets CDN — it does not expire). Embed the returned
1550
+ * `imageUrl` in a reply as markdown to show it to the user.
1551
+ *
1552
+ * ASYNC: `gpt-image-1` routinely runs 30–60s, which exceeds the API Gateway
1553
+ * 30s ceiling, so this enqueues a job (`POST /agent/images/generate` →
1554
+ * `jobId`) then polls (`GET /agent/images/{jobId}`) until it completes. The
1555
+ * worker's real failure message (e.g. an unsupported `size`) surfaces via the
1556
+ * job's `error` field.
1557
+ */
1558
+ generateImage(args: {
1559
+ prompt: string;
1560
+ model?: string;
1561
+ size?: string;
1562
+ quality?: string;
1563
+ }): Promise<{
1564
+ imageUrl: string;
1565
+ model: string;
1566
+ }>;
1567
+ }
1568
+ //# sourceMappingURL=images.d.ts.map
1569
+ //#endregion
1570
+ //#region src/domains/integrations.d.ts
1571
+ declare class IntegrationsApi extends ApiBase {
1572
+ listIntegrations(): Promise<IntegrationInstall[]>;
1573
+ getIntegrationConfig(integrationId: string): Promise<IntegrationConfigResult>;
1574
+ updateIntegrationConfig(integrationId: string, config: Record<string, unknown>): Promise<void>;
1575
+ installIntegration(integrationId: string, options?: {
1576
+ version?: string;
1577
+ config?: Record<string, unknown>;
1578
+ }): Promise<IntegrationInstall>;
1579
+ removeIntegration(integrationId: string): Promise<IntegrationInstall>;
1580
+ getOAuthUrl(provider: string, scopes?: string[]): Promise<{
1581
+ url: string;
1582
+ provider: string;
1583
+ expiresIn: number;
1584
+ }>;
1585
+ getOAuthStatus(provider: string): Promise<{
1586
+ provider: string;
1587
+ connected: boolean;
1588
+ config?: Record<string, string>;
1589
+ }>;
1590
+ getRegistry(): Promise<{
1591
+ integrations: RegistryEntry[];
1592
+ }>;
1593
+ }
1594
+ //# sourceMappingURL=integrations.d.ts.map
1595
+ //#endregion
1596
+ //#region src/domains/memory.d.ts
1597
+ declare class MemoryApi extends ApiBase {
1329
1598
  memorySearch(query: string, opts?: {
1330
1599
  limit?: number;
1331
1600
  topic?: string;
@@ -1373,8 +1642,21 @@ declare class AgentApiClient {
1373
1642
  messageCount: number;
1374
1643
  }>;
1375
1644
  memoryLoadContext(tier?: number, topicHint?: string): Promise<{
1645
+ tier: number;
1646
+ facts: {
1647
+ subject: string;
1648
+ predicate: string;
1649
+ object: string;
1650
+ since: string;
1651
+ }[];
1652
+ memories: {
1653
+ text: string;
1654
+ topic: string;
1655
+ subtopic: string;
1656
+ score: number;
1657
+ }[];
1658
+ tokenEstimate: number;
1376
1659
  formatted: string;
1377
- [key: string]: unknown;
1378
1660
  }>;
1379
1661
  memoryLookupEntity(subject: string): Promise<{
1380
1662
  subject: string;
@@ -1402,196 +1684,216 @@ declare class AgentApiClient {
1402
1684
  vectorCount: number;
1403
1685
  tripleCount: number;
1404
1686
  storageEstimateBytes: number;
1405
- lastIngestionAt?: string;
1406
- }>;
1407
- memoryLearn(args: {
1408
- text: string;
1409
- source?: string;
1410
- sourceType?: "file" | "url" | "inline";
1411
- metadata?: {
1412
- sessionId?: string;
1413
- channelId?: string;
1414
- userName?: string;
1415
- };
1416
- }): Promise<{
1417
- memoriesStored: number;
1418
- triplesStored: number;
1419
- chunks: number;
1420
- source?: string;
1421
- }>;
1422
- memoryBootstrapStatus(): Promise<{
1423
- synced: boolean;
1424
- syncedAt?: string;
1425
- sessionsBackfillSynced?: boolean;
1426
- sessionsBackfillSyncedAt?: string;
1427
- }>;
1428
- memoryBootstrapStatusMark(scope?: "files" | "sessions"): Promise<{
1429
- synced: true;
1430
- syncedAt: string;
1431
- }>;
1432
- sendSms(args: {
1433
- to: string;
1434
- body: string;
1435
- }): Promise<{
1436
- sent: boolean;
1437
- sid: string;
1438
- }>;
1439
- searchWeb(params: {
1440
- query: string;
1441
- count?: number;
1442
- offset?: number;
1443
- country?: string;
1444
- freshness?: string;
1445
- }): Promise<unknown>;
1446
- searchImages(params: {
1447
- query: string;
1448
- count?: number;
1449
- }): Promise<unknown>;
1450
- searchNews(params: {
1451
- query: string;
1452
- count?: number;
1453
- freshness?: string;
1454
- }): Promise<unknown>;
1455
- /** Search news across the selected provider's corpus. → POST /agent/news/search */
1456
- newsSearch(params: {
1457
- query: string;
1458
- provider?: NewsProvider;
1459
- source?: string;
1460
- from?: string;
1461
- to?: string;
1462
- language?: string;
1463
- category?: string;
1464
- limit?: number;
1465
- }): Promise<NewsResult>;
1466
- /** Top headlines for the selected provider. → POST /agent/news/headlines */
1467
- newsHeadlines(params?: {
1468
- provider?: NewsProvider;
1469
- category?: string;
1470
- source?: string;
1471
- language?: string;
1472
- limit?: number;
1473
- }): Promise<NewsResult>;
1474
- /**
1475
- * Semantic search across the agent's member scopes. Fan-out is gated
1476
- * server-side by `listScopes` set-inclusion (fail-closed). Pass
1477
- * `scopeType` + `scopeId` to narrow to one scope; a non-member scope
1478
- * yields empty results (never a cross-scope leak).
1479
- */
1480
- knowledgeSearch(query: string, opts?: {
1481
- limit?: number;
1482
- scopeType?: KnowledgeScopeType;
1483
- scopeId?: string;
1484
- }): Promise<KnowledgeSearchResult>;
1485
- /** Enumerate the scopes (org + teams + projects) this agent belongs to. */
1486
- listScopes(): Promise<{
1487
- scopes: KnowledgeScope[];
1687
+ lastIngestionAt?: string;
1488
1688
  }>;
1489
- /** Read a scope's structured knowledge profile (after membership check). */
1490
- getScopeProfile(scopeType: KnowledgeScopeType, scopeId: string): Promise<KnowledgeProfile>;
1491
- /** List a scope's docs (the org-files corpus; mirrored to shared/<scope>/). */
1492
- listScopeDocs(scopeType: KnowledgeScopeType, scopeId: string, opts?: {
1493
- limit?: number;
1494
- cursor?: string;
1689
+ memoryLearn(args: {
1690
+ text: string;
1691
+ source?: string;
1692
+ sourceType?: "file" | "url" | "inline";
1693
+ metadata?: {
1694
+ sessionId?: string;
1695
+ channelId?: string;
1696
+ userName?: string;
1697
+ };
1495
1698
  }): Promise<{
1496
- files: KnowledgeDoc[];
1497
- nextCursor: string | null;
1699
+ memoriesStored: number;
1700
+ triplesStored: number;
1701
+ chunks: number;
1702
+ source?: string;
1703
+ }>;
1704
+ memoryBootstrapStatus(): Promise<{
1705
+ synced: boolean;
1706
+ syncedAt?: string;
1707
+ sessionsBackfillSynced?: boolean;
1708
+ sessionsBackfillSyncedAt?: string;
1709
+ }>;
1710
+ memoryBootstrapStatusMark(scope?: "files" | "sessions"): Promise<{
1711
+ synced: true;
1712
+ syncedAt: string;
1498
1713
  }>;
1714
+ }
1715
+ //# sourceMappingURL=memory.d.ts.map
1716
+ //#endregion
1717
+ //#region src/domains/secrets.d.ts
1718
+ declare class SecretsApi extends ApiBase {
1499
1719
  /**
1500
- * Read the full text of a scope doc. Resolves a presigned download URL
1501
- * from `services/org`, then fetches the bytes directly from S3 (the one
1502
- * legitimate raw fetch in a plugin same pattern as sync).
1720
+ * Mint a fresh AES-256 data key for a specific (secret, field) pair. The
1721
+ * encryption context is rebuilt server-side from `auth.tenantId` + the body
1722
+ * fields including `fieldKey`; the agent cannot forge context for a scope
1723
+ * or field it doesn't own. Legacy single-envelope secrets are migrated to
1724
+ * `field#value` rows by the data migration, so call with `fieldKey: "value"`
1725
+ * to reach them.
1503
1726
  */
1504
- readScopeDoc(scopeType: KnowledgeScopeType, scopeId: string, filePath: string): Promise<{
1505
- filePath: string;
1506
- text: string;
1507
- }>;
1727
+ generateSecretDataKey(args: {
1728
+ scope: SecretScope;
1729
+ scopeId: string;
1730
+ secretId: string;
1731
+ fieldKey: string;
1732
+ }): Promise<GeneratedDataKey>;
1508
1733
  /**
1509
- * Write (create or overwrite) a scope doc. Two-step presigned upload:
1510
- * `services/org` returns a signed URL plus `requiredHeaders` (author /
1511
- * authorKind / message as `x-amz-meta-*`) that MUST be sent verbatim on
1512
- * the PUT, alongside the same `Content-Type` that was signed. Author and
1513
- * authorKind are server-set from the agent token — never trusted here.
1734
+ * Unwrap a wrapped data key so the agent can decrypt the envelope locally.
1735
+ * `fieldKey` MUST match the value supplied when the data key was generated
1736
+ * (it's bound into KMS encryption context); mismatch fails with
1737
+ * `InvalidCiphertextException`.
1514
1738
  */
1515
- writeScopeDoc(scopeType: KnowledgeScopeType, scopeId: string, filePath: string, content: string, opts?: {
1516
- contentType?: string;
1517
- message?: string;
1739
+ decryptSecretDataKey(args: {
1740
+ scope: SecretScope;
1741
+ scopeId: string;
1742
+ secretId: string;
1743
+ fieldKey: string;
1744
+ dataKeyCiphertext: string;
1518
1745
  }): Promise<{
1519
- filePath: string;
1746
+ plaintextKey: string;
1520
1747
  }>;
1521
1748
  /**
1522
- * Open a change request against a scope's knowledge resource. For a doc
1523
- * create/update, `services/org` returns a presigned staging PUT; this method
1524
- * uploads the proposed `content` to it (echoing the same Content-Type that
1525
- * was signed), mirroring `writeScopeDoc`. The staged body is applied to the
1526
- * canonical doc — attributed to this agent — only when a reviewer approves.
1527
- */
1528
- proposeScopeChange(scopeType: KnowledgeScopeType, scopeId: string, input: ProposeScopeChangeInput): Promise<KnowledgeChangeRequest>;
1529
- /**
1530
- * List the agent's OWN change requests in a scope (filtered server-side to
1531
- * this agent as proposer). Pass `status` to narrow to open / approved / etc.
1749
+ * Create a new secret with one or more fields. Encrypted fields must arrive
1750
+ * pre-sealed (the agent has already obtained per-field data keys via
1751
+ * `generateSecretDataKey({ ..., fieldKey })` and AES-encrypted locally).
1752
+ * Plaintext fields ship the value inline.
1532
1753
  */
1533
- listScopeChangeRequests(scopeType: KnowledgeScopeType, scopeId: string, opts?: {
1534
- status?: ChangeRequestStatus;
1535
- limit?: number;
1536
- cursor?: string;
1754
+ createSecret(args: {
1755
+ scope: SecretScope;
1756
+ scopeId: string;
1757
+ secretId: string;
1758
+ secretName: string;
1759
+ category?: SecretCategory;
1760
+ description?: string;
1761
+ tags?: string[];
1762
+ fields: {
1763
+ key: string;
1764
+ format?: FieldFormat;
1765
+ sensitivity: FieldSensitivity;
1766
+ value?: string;
1767
+ envelope?: EncryptedEnvelopeV1;
1768
+ }[];
1769
+ reason?: string;
1770
+ }): Promise<SecretAggregate>;
1771
+ /** Fetch the secret aggregate plus per-field encrypted envelopes. */
1772
+ getSecret(args: {
1773
+ scope: SecretScope;
1774
+ scopeId: string;
1775
+ secretId: string;
1537
1776
  }): Promise<{
1538
- changeRequests: KnowledgeChangeRequest[];
1539
- nextCursor: string | null;
1777
+ aggregate: SecretAggregate;
1778
+ envelopes: FieldEnvelope[];
1540
1779
  }>;
1541
- registerDatabaseCredentials(): Promise<{
1542
- connectionString: string;
1543
- username: string;
1544
- password: string;
1545
- databases: string[];
1780
+ /** Fetch one field. Plaintext: value inline. Encrypted: envelope. */
1781
+ getSecretField(args: {
1782
+ scope: SecretScope;
1783
+ scopeId: string;
1784
+ secretId: string;
1785
+ fieldKey: string;
1786
+ }): Promise<{
1787
+ key: string;
1788
+ sensitivity: FieldSensitivity;
1789
+ format?: FieldFormat;
1790
+ value?: string;
1791
+ envelope?: EncryptedEnvelopeV1;
1792
+ rotatedAt?: string;
1793
+ createdAt: string;
1794
+ updatedAt: string;
1546
1795
  }>;
1547
- reportDatabaseAudit(entry: {
1548
- database: string;
1549
- collection: string;
1550
- operation: string;
1551
- summary?: string;
1796
+ /** Add OR rotate one field. */
1797
+ setSecretField(args: {
1798
+ scope: SecretScope;
1799
+ scopeId: string;
1800
+ secretId: string;
1801
+ fieldKey: string;
1802
+ sensitivity: FieldSensitivity;
1803
+ format?: FieldFormat;
1804
+ value?: string;
1805
+ envelope?: EncryptedEnvelopeV1;
1806
+ reason?: string;
1807
+ }): Promise<{
1808
+ fieldKey: string;
1809
+ rotated: boolean;
1810
+ }>;
1811
+ /** Remove one field. */
1812
+ removeSecretField(args: {
1813
+ scope: SecretScope;
1814
+ scopeId: string;
1815
+ secretId: string;
1816
+ fieldKey: string;
1552
1817
  }): Promise<void>;
1553
- requestBrowserTakeover(args: {
1554
- instructions: string;
1555
- url?: string;
1556
- conversationId?: string;
1818
+ /** Update secret-level metadata (name/description/tags/category). */
1819
+ updateSecretMetadata(args: {
1820
+ scope: SecretScope;
1821
+ scopeId: string;
1822
+ secretId: string;
1823
+ secretName?: string;
1824
+ description?: string;
1825
+ tags?: string[];
1826
+ category?: SecretCategory;
1827
+ reason?: string;
1828
+ }): Promise<SecretAggregate>;
1829
+ /** List metadata for secrets in a scope. Optional filters route through the byFacet GSI. */
1830
+ listSecrets(args: {
1831
+ scope: SecretScope;
1832
+ scopeId: string;
1833
+ category?: SecretCategory;
1834
+ tag?: string;
1835
+ fieldKey?: string;
1836
+ }): Promise<SecretMetadata[]>;
1837
+ /** Bounded changelog read — metadata-only audit entries. */
1838
+ getSecretHistory(args: {
1839
+ scope: SecretScope;
1840
+ scopeId: string;
1841
+ secretId: string;
1842
+ limit?: number;
1843
+ cursor?: string;
1557
1844
  }): Promise<{
1558
- sessionId: string;
1559
- status: string;
1845
+ entries: ChangelogEntry[];
1846
+ nextCursor?: string;
1560
1847
  }>;
1561
- getRemoteSession(sessionId: string): Promise<RemoteSessionInfo>;
1562
- completeRemoteSession(sessionId: string): Promise<{
1848
+ /** Delete a secret (and all its field rows + tag rows + changelog rows). */
1849
+ deleteSecret(args: {
1850
+ scope: SecretScope;
1851
+ scopeId: string;
1852
+ secretId: string;
1853
+ }): Promise<void>;
1854
+ /** Enumerate scopes (org/team/project/agent) this agent can access. */
1855
+ listSecretScopes(): Promise<ScopeInfo[]>;
1856
+ }
1857
+ //# sourceMappingURL=secrets.d.ts.map
1858
+ //#endregion
1859
+ //#region src/domains/teams.d.ts
1860
+ declare class TeamsApi extends ApiBase {
1861
+ getTeamsCredentials(): Promise<{
1862
+ agentId: string;
1863
+ tenantId: string;
1864
+ azureAppId: string;
1865
+ azureBotId: string;
1866
+ azureClientSecret: string;
1867
+ botDisplayName?: string;
1868
+ teamsTenantId?: string;
1869
+ serviceUrl?: string;
1870
+ }>;
1871
+ sendTeamsMessage(data: {
1872
+ conversationId: string;
1873
+ text?: string;
1874
+ adaptiveCard?: Record<string, unknown>;
1875
+ }): Promise<{
1563
1876
  ok: boolean;
1877
+ activityId: string;
1564
1878
  }>;
1565
- /**
1566
- * Issue a request that returns the raw `Response` (no JSON parsing, no
1567
- * forced Content-Type). The caller sets `Content-Type`/`Accept` on `headers`
1568
- * and reads the body itself (`arrayBuffer()` / `json()`).
1569
- *
1570
- * A single retry fires only on the same transient statuses `request()`
1571
- * retries (authorizer-timeout 500 + LB 502/503/504) and transient network
1572
- * errors — before the route handler runs — so re-issuing a POST does not
1573
- * risk a duplicate side effect. Voice TTS/STT are effectively idempotent
1574
- * (re-synthesize / re-transcribe) and meter server-side keyed on the
1575
- * gateway requestId, so a retried transcription doesn't double-bill.
1576
- */
1577
- private rawFetch;
1578
- /**
1579
- * Text-to-speech. Returns raw PCM audio bytes plus their framing — the
1580
- * voice service defaults to 24 kHz / mono / 16-bit. Wrap in a WAV container
1581
- * to produce a playable file. Metered per character against the tenant
1582
- * credit pool server-side; TTS completes regardless of metering outcome.
1583
- */
1584
- tts(args: VoiceTtsArgs): Promise<VoiceTtsResult>;
1585
- /**
1586
- * Speech-to-text. Accepts raw linear16 (16-bit LE) mono PCM — NOT a WAV or
1587
- * other container (the endpoint transcribes with a fixed linear16 encoding,
1588
- * so a container header would be transcribed as noise). Strip any WAV header
1589
- * and pass `sampleRate` from it before calling. Metered by transcribed
1590
- * duration against the tenant credit pool server-side.
1591
- */
1592
- stt(args: VoiceSttArgs): Promise<VoiceSttResult>;
1879
+ listTeamsChannels(): Promise<{
1880
+ channels: {
1881
+ id: string;
1882
+ name: string;
1883
+ description?: string;
1884
+ }[];
1885
+ }>;
1886
+ }
1887
+ //# sourceMappingURL=teams.d.ts.map
1888
+
1889
+ //#endregion
1890
+ //#region src/index.d.ts
1891
+ interface AgentApiClient extends SyncApi, IntegrationsApi, WorkspaceApi, ConnectCredentialsApi, TeamsApi, ChatApi, SecretsApi, IdentityApi, MemoryApi, SearchApi, KnowledgeApi, DatabaseApi, MobileApi, RemoteApi, SelfApi, VoiceApi, ImagesApi, WebhooksApi {}
1892
+ declare class AgentApiClient extends ApiBase {
1893
+ constructor(config: AgentApiClientConfig);
1593
1894
  }
1594
1895
  //# sourceMappingURL=index.d.ts.map
1896
+
1595
1897
  //#endregion
1596
1898
  //#endregion
1597
1899
  //#region src/index.d.ts
@@ -1637,8 +1939,8 @@ declare const SERVER_BIN_PATH: string;
1637
1939
  type ServerProfile = 'default' | 'claude-code';
1638
1940
  interface ServerOptions {
1639
1941
  /**
1640
- * Optional override for the API client tests inject a fake so the
1641
- * server can be exercised end-to-end without real network I/O.
1942
+ * Optional pre-bound API client. Must be supplied together with `apiUrl` so
1943
+ * the client authority and the OAuth URL authority cannot diverge.
1642
1944
  */
1643
1945
  client?: AgentApiClient;
1644
1946
  /** Pre-resolved context fields. If omitted, the server calls `whoami()` itself. */
@@ -1646,7 +1948,7 @@ interface ServerOptions {
1646
1948
  agentId: string;
1647
1949
  tenantId: string;
1648
1950
  };
1649
- /** Override apiUrl reported in the ToolContext. Defaults to the resolved CLI config. */
1951
+ /** Authority bound to an injected `client`. Omit both to use resolved CLI config. */
1650
1952
  apiUrl?: string;
1651
1953
  /**
1652
1954
  * Tool surface to register. Defaults to `default` (integrations only) so
@@ -1668,9 +1970,9 @@ interface ServerOptions {
1668
1970
  * Pure construction — does not connect a transport. Callers (the bin
1669
1971
  * entry, or tests) attach `StdioServerTransport` or any other transport.
1670
1972
  *
1671
- * `resolveConfig()` is only called when neither `client` nor `apiUrl`
1672
- * is provided tests can fully construct the server without touching
1673
- * `~/.alfe/config.toml`.
1973
+ * `resolveConfig()` is only called when the main `client`/`apiUrl` pair is
1974
+ * omitted. Tests and alternate hosts can inject a complete pair without
1975
+ * touching `~/.alfe/config.toml`.
1674
1976
  */
1675
1977
  declare function createServer(opts?: ServerOptions): Promise<McpServer>;
1676
1978
  /**
@@ -1681,14 +1983,13 @@ declare function createServer(opts?: ServerOptions): Promise<McpServer>;
1681
1983
  */
1682
1984
  declare function parseProfileArg(argv: string[]): ServerProfile;
1683
1985
  /**
1684
- * Entry point boot the server on stdio. Used by `bin.ts`. Any
1685
- * startup failure is fatal: log and exit non-zero so the bundler's
1686
- * connection attempt surfaces a clear error rather than a hung
1687
- * handshake.
1986
+ * Boot the server and attach its transport. Used by `bin.ts`; tests can inject
1987
+ * an in-memory transport. Process policy (logging, exit code, signals) remains
1988
+ * in the executable boundary rather than this reusable library function.
1688
1989
  */
1689
- declare function main(opts?: {
1690
- profile?: ServerProfile;
1691
- }): Promise<void>;
1990
+ declare function main(opts?: ServerOptions & {
1991
+ transport?: Transport;
1992
+ }): Promise<McpServer>;
1692
1993
  //# sourceMappingURL=index.d.ts.map
1693
1994
 
1694
1995
  //#endregion