@alfe.ai/openclaw-sync 0.0.16 → 0.0.17

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.ts CHANGED
@@ -1,61 +1,7 @@
1
1
  import plugin, { SyncPluginConfig } from "./plugin.js";
2
2
 
3
- //#region src/config.d.ts
4
-
5
- /**
6
- * AlfeSync configuration.
7
- *
8
- * Derives credentials from `@alfe.ai/config` (~/.alfe/config.toml) so the
9
- * sync plugin works on any agent that's already logged in — no separate
10
- * `.alfesync/config.json` or manual `alfesync init` required.
11
- *
12
- * The only field not directly in @alfe.ai/config is `agentId`, which is
13
- * resolved once at startup by calling POST /auth/validate (same pattern
14
- * the gateway daemon uses to bootstrap its own identity).
15
- */
16
- interface SyncConfig {
17
- agentId: string;
18
- orgId: string;
19
- token: string;
20
- workspacePath: string;
21
- apiUrl: string;
22
- }
23
- /**
24
- * Local on-disk state directory (manifest, etc.) — separate from credentials.
25
- * Lives under ~/.alfe/sync/ so sync state stays alongside the rest of Alfe's
26
- * agent state, not scattered across the workspace.
27
- */
28
- declare function syncStateDir(): string;
29
- /**
30
- * True if the agent has logged in (~/.alfe/config.toml exists).
31
- * Sync needs no separate initialization — login is enough.
32
- */
33
- declare function isInitialized(): boolean;
34
- /**
35
- * Invalidate the in-memory config cache. Call after login changes.
36
- */
37
- declare function invalidateSyncConfigCache(): void;
38
- /**
39
- * Resolve the full sync config — apiKey + apiUrl from @alfe.ai/config,
40
- * agentId/orgId fetched once from /auth/validate.
41
- *
42
- * Returns null if the agent isn't logged in or validation fails.
43
- * Callers that require config should use requireConfig().
44
- *
45
- * Concurrent callers share a single in-flight promise; failures are
46
- * not cached so a transient API blip doesn't poison the process.
47
- */
48
- declare function resolveSyncConfig(): Promise<SyncConfig | null>;
49
- /**
50
- * Resolve config or throw with a clear message. Use in CLI entry points.
51
- */
52
- declare function requireConfig(): Promise<SyncConfig>;
53
- /**
54
- * Local-only check: does the on-disk sync state directory exist?
55
- * Used by manifest loading to decide whether to create it.
56
- */
57
- //#endregion
58
3
  //#region src/manifest.d.ts
4
+
59
5
  /**
60
6
  * AlfeSync manifest — local file manifest at `~/.alfe/sync/manifest.json`.
61
7
  *
@@ -153,197 +99,832 @@ declare function shouldIgnore(relativePath: string, patterns: string[]): boolean
153
99
  declare function filterIgnored(paths: string[], patterns: string[]): string[];
154
100
  //# sourceMappingURL=ignore.d.ts.map
155
101
  //#endregion
156
- //#region src/api-client.d.ts
157
- interface ApiClientConfig {
102
+ //#region ../agent-api-client/dist/index.d.ts
103
+ //#region ../../packages-internal/types/dist/access.d.ts
104
+
105
+ /**
106
+ * The four resource scopes at which a permission can apply.
107
+ * Order is meaningful: broader scopes first (`org`) → narrower last (`agent`).
108
+ *
109
+ * `IntegrationScope` in integration.ts and `SecretScope` in secrets.ts are
110
+ * intentional aliases of this same enum — there is only one concept of
111
+ * "scope" in Alfe.
112
+ */
113
+ declare const ResourceScope: {
114
+ readonly Org: "org";
115
+ readonly Team: "team";
116
+ readonly Project: "project";
117
+ readonly Agent: "agent";
118
+ };
119
+ type ResourceScope = (typeof ResourceScope)[keyof typeof ResourceScope];
120
+ /** Ordered tuple of resource scope string values (broad → narrow). */
121
+ //#endregion
122
+ //#region ../../packages-internal/types/dist/integration.d.ts
123
+ /** Controls where an integration appears: public (everyone), hidden (nowhere) */
124
+ declare const IntegrationVisibility: {
125
+ readonly Public: "public";
126
+ readonly Hidden: "hidden";
127
+ };
128
+ type IntegrationVisibility = (typeof IntegrationVisibility)[keyof typeof IntegrationVisibility];
129
+ /** Scope at which an integration is installed */
130
+ declare const IntegrationScope: {
131
+ readonly Org: "org";
132
+ readonly Team: "team";
133
+ readonly Project: "project";
134
+ readonly Agent: "agent";
135
+ };
136
+ type IntegrationScope = ResourceScope;
137
+ declare const IntegrationDesiredStatus: {
138
+ readonly Active: "active";
139
+ readonly Removed: "removed";
140
+ };
141
+ type IntegrationDesiredStatus = (typeof IntegrationDesiredStatus)[keyof typeof IntegrationDesiredStatus];
142
+ declare const IntegrationActualStatus: {
143
+ readonly Installing: "installing";
144
+ readonly Active: "active";
145
+ readonly Error: "error";
146
+ readonly Removing: "removing";
147
+ readonly Inactive: "inactive";
148
+ readonly Unknown: "unknown";
149
+ };
150
+ type IntegrationActualStatus = (typeof IntegrationActualStatus)[keyof typeof IntegrationActualStatus];
151
+ interface IntegrationInstall {
152
+ scope: IntegrationScope;
153
+ scopeId: string;
154
+ integrationId: string;
155
+ tenantId: string;
156
+ desiredStatus: IntegrationDesiredStatus;
157
+ actualStatus: IntegrationActualStatus;
158
+ version: string;
159
+ config: Record<string, unknown>;
160
+ errorMessage: string;
161
+ installedAt: string;
162
+ updatedAt: string;
163
+ }
164
+ /** @deprecated Use IntegrationInstall instead */
165
+
166
+ interface IntegrationConfigSchemaField {
167
+ key: string;
168
+ label: string;
169
+ type: string;
170
+ description?: string;
171
+ required?: boolean;
172
+ default?: string | number | boolean;
173
+ options?: string[];
174
+ select_options?: {
175
+ value: string;
176
+ label: string;
177
+ }[];
178
+ oauth_provider?: string;
179
+ oauth_scopes?: string[];
180
+ oauth_integration_id?: string;
181
+ editable?: string;
182
+ hidden?: boolean;
183
+ }
184
+ interface IntegrationConfigResult {
185
+ integrationId: string;
186
+ config: Record<string, unknown>;
187
+ configSchema: IntegrationConfigSchemaField[];
188
+ }
189
+ interface RegistryEntry {
190
+ id: string;
191
+ name: string;
192
+ description: string;
193
+ versions: string[];
194
+ latest: string;
195
+ repository: string;
196
+ commit: string;
197
+ icon?: string;
198
+ author?: {
199
+ name: string;
200
+ url?: string;
201
+ } | string;
202
+ pricing?: {
203
+ type: "free" | "paid" | "usage";
204
+ price?: number;
205
+ currency?: string;
206
+ interval?: "month" | "year";
207
+ description?: string;
208
+ };
209
+ features?: string[];
210
+ preview_images?: string[];
211
+ config_schema?: IntegrationConfigSchemaField[];
212
+ supported_agents?: string[];
213
+ /** Scopes where this integration can be installed */
214
+ supported_scopes?: IntegrationScope[];
215
+ /** Visibility status — controls where integration appears */
216
+ visibility?: IntegrationVisibility;
217
+ }
218
+ //# sourceMappingURL=integration.d.ts.map
219
+ //#endregion
220
+ //#region ../../packages-internal/types/dist/secrets.d.ts
221
+ /** Scope levels at which a secret can be owned. Aliased to ResourceScope. */
222
+ type SecretScope = ResourceScope;
223
+ /**
224
+ * v1 encrypted envelope as persisted by services/secrets and exchanged with
225
+ * agents. Values are AES-256-GCM ciphertext; iv/authTag/ciphertext/dataKeyCiphertext
226
+ * are all base64-encoded.
227
+ */
228
+ interface EncryptedEnvelopeV1 {
229
+ version: 1;
230
+ iv: string;
231
+ ciphertext: string;
232
+ authTag: string;
233
+ dataKeyCiphertext: string;
234
+ }
235
+ /** Opaque metadata about a secret row — never includes plaintext. */
236
+ interface SecretMetadata {
237
+ secretId: string;
238
+ secretName: string;
239
+ description?: string;
240
+ tags?: string[];
241
+ createdAt: string;
242
+ updatedAt: string;
243
+ rotatedAt?: string;
244
+ }
245
+ /** A single secret row including its encrypted envelope. */
246
+ interface SecretEnvelopeResponse extends SecretMetadata {
247
+ envelope: EncryptedEnvelopeV1;
248
+ }
249
+ /** A scope the caller can read or write secrets in. */
250
+ interface ScopeInfo {
251
+ scope: SecretScope;
252
+ scopeId: string;
253
+ name?: string;
254
+ }
255
+ /**
256
+ * KMS-issued data key, returned by the secrets service's
257
+ * `/secrets/generate-data-key` KMS proxy endpoint. The plaintext key is
258
+ * returned base64-encoded; callers MUST decode it to a Buffer and zero the
259
+ * Buffer after use — never keep the plaintext as a JS string.
260
+ */
261
+ interface GeneratedDataKey {
262
+ plaintextKey: string;
263
+ dataKeyCiphertext: string;
264
+ }
265
+ //# sourceMappingURL=secrets.d.ts.map
266
+ //#endregion
267
+ //#region src/index.d.ts
268
+ interface AgentApiClientConfig {
269
+ apiKey: string;
158
270
  apiUrl: string;
159
- token: string;
271
+ }
272
+ interface SyncAgentInfo {
160
273
  agentId: string;
274
+ tenantId: string;
275
+ displayName: string;
276
+ s3Prefix: string;
277
+ status: "stale" | "syncing" | "synced";
278
+ fileCount?: number;
279
+ totalSize?: number;
280
+ lastSync?: string;
161
281
  }
162
- interface PresignResult {
163
- path: string;
164
- url: string;
165
- expiresAt: string;
282
+ interface SyncManifestEntry {
283
+ hash: string;
284
+ size: number;
285
+ modified: string;
286
+ etag?: string;
287
+ storageClass?: string;
288
+ compressed?: boolean;
166
289
  }
167
- interface AgentStats {
290
+ interface SyncManifest {
291
+ version: 1;
168
292
  agentId: string;
169
- standardBytes: number;
170
- glacierBytes: number;
171
- fileCount: number;
172
- lastSyncAt: string | null;
293
+ lastSync: string;
294
+ files: Record<string, SyncManifestEntry>;
173
295
  }
174
- interface RegisterAgentResult {
175
- agent: {
176
- agentId: string;
177
- orgId: string;
178
- displayName: string;
179
- status: string;
180
- createdAt: string;
181
- };
296
+ interface SyncPresignedUrl {
297
+ path: string;
298
+ url: string;
299
+ expiresAt: string;
182
300
  }
183
- interface ConfirmResult {
301
+ interface SyncConfirmedUpload {
184
302
  filePath: string;
185
303
  hash: string;
186
304
  size: number;
187
- storageClass: string;
305
+ storageClass: "STANDARD" | "GLACIER_IR";
188
306
  syncedAt: string;
189
307
  }
190
- interface ReconstructResult {
308
+ interface SyncReconstructFile {
309
+ path: string;
310
+ size: number;
311
+ url: string;
312
+ storageClass?: string;
313
+ compressed?: boolean;
314
+ }
315
+ interface SyncReconstructBundle {
191
316
  agentId: string;
192
317
  mode: "full" | "active" | "memory";
193
318
  fileCount: number;
194
319
  totalSize: number;
195
- files: {
196
- path: string;
197
- url: string;
198
- size: number;
199
- compressed: boolean;
200
- expiresAt: string;
201
- }[];
202
- generatedAt: string;
320
+ files: SyncReconstructFile[];
203
321
  expiresAt: string;
204
322
  }
205
- interface FileHistoryEntry {
206
- versionId: string;
207
- isLatest: boolean;
323
+ interface SyncAgentStats {
324
+ agentId: string;
325
+ standardBytes: number;
326
+ glacierBytes: number;
327
+ fileCount: number;
328
+ lastSyncAt: string | null;
329
+ }
330
+ interface SyncFileEntry {
331
+ filePath: string;
332
+ size: number;
333
+ modified: string;
334
+ contentHash: string;
335
+ storageClass?: string;
336
+ compressed?: boolean;
337
+ }
338
+ interface SyncSessionEntry {
339
+ sessionId: string;
340
+ size: number;
208
341
  lastModified: string;
342
+ storageClass?: string;
343
+ isArchived: boolean;
344
+ }
345
+ interface SyncSessionContent {
346
+ sessionId: string;
347
+ content: string;
348
+ compressed: boolean;
349
+ }
350
+ interface SharedFileEntry {
351
+ filePath: string;
352
+ fileName: string;
209
353
  size: number;
210
- etag?: string;
354
+ contentType?: string;
211
355
  }
212
- /**
213
- * Create an AlfeSync API client.
214
- */
215
- declare function createApiClient(config: ApiClientConfig): {
216
- /**
217
- * Get the remote manifest for this agent.
218
- */
219
- getManifest(): Promise<RemoteManifest>;
220
- /**
221
- * Request a presigned PUT URL for uploading a file.
222
- */
223
- presignPut(filePath: string, contentType?: string): Promise<PresignResult>;
224
- /**
225
- * Request presigned PUT URLs for multiple files.
226
- */
227
- presignPutBatch(files: {
228
- path: string;
229
- contentType?: string;
230
- }[]): Promise<PresignResult[]>;
231
- /**
232
- * Confirm a presigned upload completed — updates DynamoDB.
233
- */
234
- confirmUpload(filePath: string, hash: string, size: number, storageClass?: "STANDARD" | "GLACIER_IR"): Promise<ConfirmResult>;
235
- /**
236
- * Request a presigned GET URL for downloading a file.
237
- */
238
- presignGet(filePath: string): Promise<PresignResult>;
239
- /**
240
- * Request presigned GET URLs for multiple files.
241
- */
242
- presignGetBatch(paths: string[]): Promise<PresignResult[]>;
356
+ declare class AgentApiClient {
357
+ private readonly apiKey;
358
+ private readonly apiUrl;
359
+ constructor(config: AgentApiClientConfig);
360
+ private request;
361
+ syncRegister(args?: {
362
+ displayName?: string;
363
+ }): Promise<{
364
+ agent: SyncAgentInfo;
365
+ }>;
366
+ syncGetManifest(): Promise<SyncManifest>;
367
+ syncPresign(args: {
368
+ files: {
369
+ path: string;
370
+ operation: "put" | "get";
371
+ contentType?: string;
372
+ }[];
373
+ }): Promise<{
374
+ urls: SyncPresignedUrl[];
375
+ }>;
376
+ syncConfirmUpload(args: {
377
+ filePath: string;
378
+ hash: string;
379
+ size: number;
380
+ storageClass?: "STANDARD" | "GLACIER_IR";
381
+ }): Promise<SyncConfirmedUpload>;
382
+ syncReconstruct(args: {
383
+ mode: "full" | "active" | "memory";
384
+ }): Promise<SyncReconstructBundle>;
385
+ syncGetStats(): Promise<SyncAgentStats>;
386
+ syncListFiles(args?: {
387
+ prefix?: string;
388
+ }): Promise<{
389
+ files: SyncFileEntry[];
390
+ }>;
391
+ syncListSessions(): Promise<{
392
+ sessions: SyncSessionEntry[];
393
+ }>;
394
+ syncGetSession(sessionId: string): Promise<SyncSessionContent>;
395
+ syncDeleteFile(filePath: string): Promise<{
396
+ removed: boolean;
397
+ }>;
398
+ sharedListFiles(args: {
399
+ scope: "org" | "team" | "project";
400
+ scopeId: string;
401
+ }): Promise<{
402
+ files: SharedFileEntry[];
403
+ nextCursor: string | null;
404
+ }>;
405
+ sharedDownloadUrl(args: {
406
+ scope: "org" | "team" | "project";
407
+ scopeId: string;
408
+ filePath: string;
409
+ }): Promise<{
410
+ downloadUrl: string;
411
+ expiresIn: number;
412
+ }>;
413
+ listIntegrations(): Promise<IntegrationInstall[]>;
414
+ getIntegrationConfig(integrationId: string): Promise<IntegrationConfigResult>;
415
+ updateIntegrationConfig(integrationId: string, config: Record<string, unknown>): Promise<void>;
416
+ installIntegration(integrationId: string, options?: {
417
+ version?: string;
418
+ config?: Record<string, unknown>;
419
+ }): Promise<IntegrationInstall>;
420
+ removeIntegration(integrationId: string): Promise<IntegrationInstall>;
421
+ getOAuthUrl(provider: string, scopes?: string[]): Promise<{
422
+ url: string;
423
+ provider: string;
424
+ expiresIn: number;
425
+ }>;
426
+ getOAuthStatus(provider: string): Promise<{
427
+ provider: string;
428
+ connected: boolean;
429
+ config?: Record<string, string>;
430
+ }>;
431
+ getRegistry(): Promise<{
432
+ integrations: RegistryEntry[];
433
+ }>;
434
+ getGoogleCredentials(): Promise<{
435
+ accounts?: {
436
+ email: string;
437
+ refreshToken: string;
438
+ clientId: string;
439
+ clientSecret: string;
440
+ enabledServices?: string[];
441
+ isDefault: boolean;
442
+ displayName?: string;
443
+ }[];
444
+ email: string;
445
+ refreshToken: string;
446
+ clientId: string;
447
+ clientSecret: string;
448
+ projectId: string;
449
+ enabledServices?: string[];
450
+ }>;
451
+ disconnectGoogleAccount(email: string): Promise<{
452
+ accounts: {
453
+ email: string;
454
+ displayName?: string;
455
+ isDefault: boolean;
456
+ }[];
457
+ }>;
458
+ setDefaultGoogleAccount(email: string): Promise<{
459
+ accounts: {
460
+ email: string;
461
+ displayName?: string;
462
+ isDefault: boolean;
463
+ }[];
464
+ }>;
465
+ getGoogleChatCredentials(): Promise<{
466
+ email: string;
467
+ refreshToken: string;
468
+ clientId: string;
469
+ clientSecret: string;
470
+ displayName?: string;
471
+ }>;
472
+ getGithubCredentials(): Promise<{
473
+ login: string;
474
+ accessToken: string;
475
+ }>;
476
+ getXeroCredentials(): Promise<{
477
+ accessToken: string;
478
+ accessTokenExpiresAt: string;
479
+ xeroTenantId: string;
480
+ }>;
481
+ refreshXeroToken(): Promise<{
482
+ accessToken: string;
483
+ expiresAt: string;
484
+ }>;
485
+ getNotionCredentials(): Promise<{
486
+ accessToken: string;
487
+ workspaceId: string;
488
+ workspaceName: string;
489
+ }>;
490
+ getAtlassianCredentials(): Promise<{
491
+ accessToken: string;
492
+ refreshToken: string;
493
+ accessTokenExpiresAt: string;
494
+ cloudId: string;
495
+ siteName: string;
496
+ siteUrl: string;
497
+ email: string;
498
+ enabledProducts: string[];
499
+ clientId: string;
500
+ clientSecret: string;
501
+ }>;
502
+ refreshAtlassianToken(): Promise<{
503
+ accessToken: string;
504
+ expiresAt: string;
505
+ }>;
506
+ getMYOBCredentials(): Promise<{
507
+ accessToken: string;
508
+ accessTokenExpiresAt: string;
509
+ myobBusinessId: string;
510
+ clientId: string;
511
+ }>;
512
+ refreshMYOBToken(): Promise<{
513
+ accessToken: string;
514
+ expiresAt: string;
515
+ }>;
516
+ getTeamsCredentials(): Promise<{
517
+ agentId: string;
518
+ tenantId: string;
519
+ azureAppId: string;
520
+ azureBotId: string;
521
+ azureClientSecret: string;
522
+ botDisplayName?: string;
523
+ teamsTenantId?: string;
524
+ serviceUrl?: string;
525
+ }>;
526
+ sendTeamsMessage(data: {
527
+ conversationId: string;
528
+ text?: string;
529
+ adaptiveCard?: Record<string, unknown>;
530
+ }): Promise<{
531
+ ok: boolean;
532
+ activityId: string;
533
+ }>;
534
+ listTeamsChannels(): Promise<{
535
+ channels: {
536
+ id: string;
537
+ name: string;
538
+ description?: string;
539
+ }[];
540
+ }>;
541
+ presignAttachments(files: {
542
+ filename: string;
543
+ mimeType: string;
544
+ size: number;
545
+ }[]): Promise<{
546
+ attachments: {
547
+ id: string;
548
+ uploadUrl: string;
549
+ downloadUrl: string;
550
+ s3Key: string;
551
+ expiresAt: string;
552
+ }[];
553
+ }>;
554
+ recordActivity(data: {
555
+ userId?: string;
556
+ channel: string;
557
+ role: "user" | "assistant";
558
+ }): Promise<{
559
+ recorded: boolean;
560
+ }>;
243
561
  /**
244
- * Get agent storage stats.
562
+ * Mint a fresh AES-256 data key for a new secret or rotation. The encryption
563
+ * context is rebuilt server-side from `auth.tenantId` + the body fields; the
564
+ * agent cannot forge context for a scope it doesn't own.
245
565
  */
246
- getStats(): Promise<AgentStats>;
566
+ generateSecretDataKey(args: {
567
+ scope: SecretScope;
568
+ scopeId: string;
569
+ secretId: string;
570
+ }): Promise<GeneratedDataKey>;
247
571
  /**
248
- * Register this agent with the sync service.
572
+ * Unwrap a wrapped data key so the agent can decrypt the envelope locally.
573
+ * KMS Decrypt will fail with `InvalidCiphertextException` if the envelope
574
+ * was tampered with in a way that changes `{ tenantId, scope, scopeId, secretId }`.
249
575
  */
250
- registerAgent(displayName?: string): Promise<RegisterAgentResult>;
576
+ decryptSecretDataKey(args: {
577
+ scope: SecretScope;
578
+ scopeId: string;
579
+ secretId: string;
580
+ dataKeyCiphertext: string;
581
+ }): Promise<{
582
+ plaintextKey: string;
583
+ }>;
584
+ /** Upload a pre-encrypted envelope for a secret. */
585
+ putSecretEnvelope(args: {
586
+ scope: SecretScope;
587
+ scopeId: string;
588
+ secretId: string;
589
+ secretName: string;
590
+ envelope: EncryptedEnvelopeV1;
591
+ description?: string;
592
+ tags?: string[];
593
+ }): Promise<{
594
+ secretId: string;
595
+ }>;
596
+ /** Fetch the encrypted envelope for a single secret. */
597
+ getSecretEnvelope(args: {
598
+ scope: SecretScope;
599
+ scopeId: string;
600
+ secretId: string;
601
+ }): Promise<SecretEnvelopeResponse>;
602
+ /** List metadata (never envelopes) for secrets in a scope. */
603
+ listSecrets(args: {
604
+ scope: SecretScope;
605
+ scopeId: string;
606
+ }): Promise<SecretMetadata[]>;
607
+ /** Delete a secret. */
608
+ deleteSecret(args: {
609
+ scope: SecretScope;
610
+ scopeId: string;
611
+ secretId: string;
612
+ }): Promise<void>;
613
+ /** Enumerate scopes (org/team/project/agent) this agent can access. */
614
+ listSecretScopes(): Promise<ScopeInfo[]>;
615
+ resolveIdentity(args: {
616
+ provider: string;
617
+ platformId: string;
618
+ kind?: "user" | "agent" | "service" | "bot" | "workspace";
619
+ displayName?: string;
620
+ }): Promise<{
621
+ identityId: string | null;
622
+ status: string;
623
+ accessAllowed: boolean;
624
+ created?: boolean;
625
+ reason?: string;
626
+ }>;
627
+ searchIdentities(args?: {
628
+ q?: string;
629
+ status?: string;
630
+ limit?: number;
631
+ }): Promise<{
632
+ identities: unknown[];
633
+ }>;
634
+ getIdentityContext(identityId: string): Promise<{
635
+ context: unknown;
636
+ }>;
637
+ mergeIdentities(survivorId: string, args: {
638
+ mergedId: string;
639
+ changedBy: {
640
+ type: string;
641
+ id: string;
642
+ name?: string;
643
+ };
644
+ }): Promise<{
645
+ ok: boolean;
646
+ error?: string;
647
+ }>;
648
+ unmergeIdentity(identityId: string, args: {
649
+ changedBy: {
650
+ type: string;
651
+ id: string;
652
+ name?: string;
653
+ };
654
+ }): Promise<{
655
+ ok: boolean;
656
+ error?: string;
657
+ }>;
658
+ addIdentityNote(identityId: string, args: {
659
+ content: string;
660
+ category?: string;
661
+ changedBy: {
662
+ type: string;
663
+ id: string;
664
+ name?: string;
665
+ };
666
+ }): Promise<{
667
+ noteId: string | null;
668
+ }>;
669
+ tagIdentity(identityId: string, args: {
670
+ tag: string;
671
+ action: "add" | "remove";
672
+ changedBy: {
673
+ type: string;
674
+ id: string;
675
+ name?: string;
676
+ };
677
+ }): Promise<{
678
+ ok: boolean;
679
+ }>;
680
+ getIdentityChangelog(identityId: string, args?: {
681
+ limit?: number;
682
+ }): Promise<{
683
+ entries: unknown[];
684
+ }>;
685
+ rollbackIdentity(identityId: string, args: {
686
+ targetVersion: number;
687
+ changedBy: {
688
+ type: string;
689
+ id: string;
690
+ name?: string;
691
+ };
692
+ }): Promise<{
693
+ ok: boolean;
694
+ entry?: unknown;
695
+ }>;
696
+ requestIdentityVerification(args: {
697
+ claimedIdentityId: string;
698
+ requestingIdentityId: string;
699
+ requestingProvider: string;
700
+ requestingPlatformId: string;
701
+ preferredChannel?: "mobile" | "email";
702
+ /**
703
+ * Phase 2: agent-supplied contact endpoint. When provided, the top-level
704
+ * `preferredChannel` is ignored — the contact's channel wins.
705
+ */
706
+ contact?: {
707
+ channel: "email" | "mobile";
708
+ value: string;
709
+ };
710
+ }): Promise<{
711
+ verificationId: string;
712
+ channel: string;
713
+ deliveredTo: string;
714
+ expiresAt: string;
715
+ availableChannels: {
716
+ channel: string;
717
+ deliveredTo: string;
718
+ }[];
719
+ } | {
720
+ error: string;
721
+ }>;
722
+ confirmIdentityVerification(args: {
723
+ claimedIdentityId: string;
724
+ verificationId: string;
725
+ phrase: string;
726
+ }): Promise<{
727
+ verified: boolean;
728
+ identityId?: string;
729
+ /** Phase 2: how the confirm resolved — Scenario A vs B. */
730
+ action?: "merged" | "contact_verified";
731
+ error?: string;
732
+ }>;
251
733
  /**
252
- * Get file version history.
734
+ * Update display-shape fields on an Identity. Body excludes `email` /
735
+ * `phone` / `title` / `company` / `metadata` per Section D4 — contacts go
736
+ * via the verify flow, title/company live on OrgMembership, metadata is
737
+ * not agent-writable.
253
738
  */
254
- getFileHistory(filePath: string): Promise<FileHistoryEntry[]>;
739
+ updateIdentity(identityId: string, args: {
740
+ name?: string;
741
+ avatarUrl?: string;
742
+ timezone?: string;
743
+ locale?: string;
744
+ }): Promise<{
745
+ ok: boolean;
746
+ }>;
255
747
  /**
256
- * Generate a reconstruction bundle.
748
+ * Phase 2 (Section H): server-side verification of a Google Chat sender via
749
+ * the agent's existing Google OAuth credentials. Returns the resolved
750
+ * identity (created or matched via Scenario-B email enrichment).
257
751
  */
258
- reconstruct(mode?: "full" | "active" | "memory"): Promise<ReconstructResult>;
259
- };
260
- type ApiClient = ReturnType<typeof createApiClient>;
261
- //# sourceMappingURL=api-client.d.ts.map
752
+ resolveGoogleChatSender(args: {
753
+ senderUserId: string;
754
+ spaceId?: string;
755
+ }): Promise<{
756
+ identityId: string | null;
757
+ status: string;
758
+ accessAllowed: boolean;
759
+ }>;
760
+ memorySearch(query: string, opts?: {
761
+ limit?: number;
762
+ topic?: string;
763
+ subtopic?: string;
764
+ tag?: string;
765
+ includeKnowledge?: boolean;
766
+ }): Promise<{
767
+ facts: {
768
+ subject: string;
769
+ predicate: string;
770
+ object: string;
771
+ since: string;
772
+ confidence: number;
773
+ }[];
774
+ memories: {
775
+ id: string;
776
+ text: string;
777
+ topic: string;
778
+ subtopic: string;
779
+ tag: string;
780
+ importance: number;
781
+ timestamp: number;
782
+ score: number;
783
+ }[];
784
+ }>;
785
+ memoryStore(text: string, opts?: {
786
+ topic?: string;
787
+ subtopic?: string;
788
+ tag?: string;
789
+ importance?: number;
790
+ }): Promise<{
791
+ memoryId: string;
792
+ }>;
793
+ memoryIngest(sessionKey: string, messages: {
794
+ role: string;
795
+ content: string;
796
+ index: number;
797
+ timestamp?: string;
798
+ }[], metadata?: {
799
+ channelId?: string;
800
+ userId?: string;
801
+ userName?: string;
802
+ }): Promise<{
803
+ queued: boolean;
804
+ messageCount: number;
805
+ }>;
806
+ memoryLoadContext(tier?: number, topicHint?: string): Promise<{
807
+ formatted: string;
808
+ [key: string]: unknown;
809
+ }>;
810
+ memoryLookupEntity(subject: string): Promise<{
811
+ subject: string;
812
+ triples: {
813
+ tripleId: string;
814
+ predicate: string;
815
+ object: string;
816
+ validFrom: string;
817
+ validTo?: string;
818
+ confidence: number;
819
+ }[];
820
+ }>;
821
+ memoryNavigate(): Promise<{
822
+ topics: {
823
+ name: string;
824
+ tripleCount: number;
825
+ subtopics: string[];
826
+ }[];
827
+ cursor: string | null;
828
+ }>;
829
+ memoryDelete(memoryId: string): Promise<{
830
+ deleted: boolean;
831
+ }>;
832
+ memoryStats(): Promise<{
833
+ vectorCount: number;
834
+ tripleCount: number;
835
+ storageEstimateBytes: number;
836
+ lastIngestionAt?: string;
837
+ }>;
838
+ searchWeb(params: {
839
+ query: string;
840
+ count?: number;
841
+ offset?: number;
842
+ country?: string;
843
+ freshness?: string;
844
+ }): Promise<unknown>;
845
+ searchImages(params: {
846
+ query: string;
847
+ count?: number;
848
+ }): Promise<unknown>;
849
+ searchNews(params: {
850
+ query: string;
851
+ count?: number;
852
+ freshness?: string;
853
+ }): Promise<unknown>;
854
+ registerDatabaseCredentials(): Promise<{
855
+ connectionString: string;
856
+ username: string;
857
+ password: string;
858
+ databases: string[];
859
+ }>;
860
+ reportDatabaseAudit(entry: {
861
+ database: string;
862
+ collection: string;
863
+ operation: string;
864
+ summary?: string;
865
+ }): Promise<void>;
866
+ }
867
+ //# sourceMappingURL=index.d.ts.map
868
+ //#endregion
262
869
  //#endregion
263
870
  //#region src/sync-engine.d.ts
264
- /**
265
- * AlfeSync engine — orchestrates push, pull, and full sync operations.
266
- *
267
- * Handles:
268
- * - push(paths[]): upload changed files to S3
269
- * - pull(): download files newer on remote
270
- * - fullSync(): bidirectional sync with conflict detection
271
- *
272
- * Conflict resolution: if remote file is newer than local manifest entry
273
- * AND local file has changed → write `.conflict-{timestamp}` alongside original.
274
- */
275
871
  interface SyncResult {
276
872
  pushed: number;
277
873
  pulled: number;
278
874
  conflicts: number;
279
875
  errors: number;
280
876
  }
877
+ interface SyncEngineOptions {
878
+ workspacePath: string;
879
+ client: AgentApiClient;
880
+ }
281
881
  /**
282
- * Create a sync engine. Workspace path defaults to `config.workspacePath`
283
- * from the resolved Alfe config, but can be overridden (e.g. for tests).
882
+ * Construct a sync engine bound to a workspace + agent API client.
883
+ *
884
+ * The client is constructed once in plugin.ts (or the CLI) and passed in,
885
+ * so credentials never leak into multiple places.
284
886
  */
285
- declare function createSyncEngine(workspacePathOverride?: string): Promise<{
286
- config: SyncConfig;
287
- client: {
288
- getManifest(): Promise<RemoteManifest>;
289
- presignPut(filePath: string, contentType?: string): Promise<PresignResult>;
290
- presignPutBatch(files: {
291
- path: string;
292
- contentType?: string;
293
- }[]): Promise<PresignResult[]>;
294
- confirmUpload(filePath: string, hash: string, size: number, storageClass?: "STANDARD" | "GLACIER_IR"): Promise<ConfirmResult>;
295
- presignGet(filePath: string): Promise<PresignResult>;
296
- presignGetBatch(paths: string[]): Promise<PresignResult[]>;
297
- getStats(): Promise<AgentStats>;
298
- registerAgent(displayName?: string): Promise<RegisterAgentResult>;
299
- getFileHistory(filePath: string): Promise<FileHistoryEntry[]>;
300
- reconstruct(mode?: "full" | "active" | "memory"): Promise<ReconstructResult>;
301
- };
887
+ declare function createSyncEngine({
888
+ workspacePath,
889
+ client
890
+ }: SyncEngineOptions): {
891
+ workspacePath: string;
892
+ client: AgentApiClient;
302
893
  /**
303
- * Push changed files to remote.
304
- *
305
- * If paths are provided, only push those files.
306
- * If no paths, detect all changed files and push them.
894
+ * Upload changed files. Pass `paths` for an explicit list, or omit
895
+ * to scan the workspace for anything that drifted from the manifest.
307
896
  */
308
897
  push(paths?: string[], options?: {
309
898
  quiet?: boolean;
310
899
  filter?: string;
311
900
  }): Promise<SyncResult>;
312
- /**
313
- * Pull files from remote that are newer than local.
314
- */
901
+ /** Download files newer on remote. */
315
902
  pull(options?: {
316
903
  quiet?: boolean;
317
904
  }): Promise<SyncResult>;
318
905
  /**
319
- * Full bidirectional sync with conflict detection.
320
- *
321
- * For conflicts: if remote file is newer than local manifest entry AND
322
- * local file has changed → write `.conflict-{timestamp}` file alongside
323
- * the original, then pull the remote version.
906
+ * Bidirectional sync. True conflicts (changed on both sides) are saved
907
+ * locally as `.conflict-<ts>` files and the remote version wins.
324
908
  */
325
909
  fullSync(options?: {
326
910
  quiet?: boolean;
327
911
  }): Promise<SyncResult>;
328
912
  /**
329
- * Pull specific files by path without a full manifest diff.
330
- *
331
- * Used for notification-driven pulls where we already know which
332
- * files changed on the remote.
913
+ * Pull a known list of files (used for relay-driven notifications,
914
+ * where we already know which paths changed remotely).
333
915
  */
334
916
  pullFiles(paths: string[], options?: {
335
917
  quiet?: boolean;
336
918
  }): Promise<SyncResult>;
337
919
  /**
338
- * Remove a file locally and from the manifest.
339
- *
340
- * Used for notification-driven deletes when a remote file is removed.
920
+ * Delete a file locally and from the manifest. Used when the sync relay
921
+ * tells us a file was removed remotely.
341
922
  */
342
923
  removeLocalFile(filePath: string, options?: {
343
924
  quiet?: boolean;
344
925
  }): Promise<void>;
345
- }>;
346
- type SyncEngine = Awaited<ReturnType<typeof createSyncEngine>>;
926
+ };
927
+ type SyncEngine = ReturnType<typeof createSyncEngine>;
347
928
  //# sourceMappingURL=sync-engine.d.ts.map
348
929
  //#endregion
349
930
  //#region src/watcher.d.ts
@@ -377,11 +958,9 @@ interface UploadResult {
377
958
  error?: string;
378
959
  }
379
960
  /**
380
- * Upload multiple files to S3.
381
- *
382
- * Uploads are performed in parallel with a concurrency limit.
961
+ * Upload many files, batched by `concurrency`.
383
962
  */
384
- declare function uploadFiles(workspacePath: string, relativePaths: string[], client: ApiClient, options?: {
963
+ declare function uploadFiles(workspacePath: string, relativePaths: string[], client: AgentApiClient, options?: {
385
964
  concurrency?: number;
386
965
  quiet?: boolean;
387
966
  }): Promise<UploadResult[]>;
@@ -394,26 +973,30 @@ interface DownloadResult {
394
973
  size?: number;
395
974
  error?: string;
396
975
  }
397
- /**
398
- * Download multiple files from S3.
399
- *
400
- * Downloads are performed in parallel with a concurrency limit.
401
- */
402
- declare function downloadFiles(workspacePath: string, relativePaths: string[], client: ApiClient, remoteManifest?: RemoteManifest, options?: {
976
+ declare function downloadFiles(workspacePath: string, relativePaths: string[], client: AgentApiClient, remoteManifest?: RemoteManifest, options?: {
403
977
  concurrency?: number;
404
978
  quiet?: boolean;
405
979
  }): Promise<DownloadResult[]>;
406
980
  //# sourceMappingURL=downloader.d.ts.map
407
981
  //#endregion
408
- //#region src/shared-sync.d.ts
982
+ //#region src/retry.d.ts
409
983
  /**
410
- * Shared file sync engine for org/team/project scoped files.
411
- *
412
- * Syncs shared files to a `shared/` directory in the agent's workspace,
413
- * organized by scope: shared/org/, shared/teams/{id}/, shared/projects/{id}/
414
- *
415
- * Uses the agent self-service API (/agents/org/...) with the agent's API key.
984
+ * Tiny retry helper used by uploader/downloader. Extracted so both
985
+ * use the same timing and surface the same final error shape.
416
986
  */
987
+ interface RetryOptions {
988
+ maxRetries?: number;
989
+ baseDelayMs?: number;
990
+ }
991
+ /**
992
+ * Run `fn` up to `maxRetries + 1` times with exponential backoff
993
+ * (`base * 2^attempt`). Returns the first successful value, or rethrows
994
+ * the last error.
995
+ */
996
+ declare function withRetry<T>(fn: () => Promise<T>, options?: RetryOptions): Promise<T>;
997
+ //# sourceMappingURL=retry.d.ts.map
998
+ //#endregion
999
+ //#region src/shared-sync.d.ts
417
1000
  interface SharedScope {
418
1001
  scopeType: "team" | "project" | "org";
419
1002
  scopeId: string;
@@ -421,9 +1004,7 @@ interface SharedScope {
421
1004
  }
422
1005
  interface SharedSyncConfig {
423
1006
  workspacePath: string;
424
- apiUrl: string;
425
- token: string;
426
- agentId: string;
1007
+ client: AgentApiClient;
427
1008
  }
428
1009
  interface PluginLogger {
429
1010
  info(msg: string): void;
@@ -440,5 +1021,5 @@ interface SharedSyncEngine {
440
1021
  }
441
1022
  declare function createSharedSyncEngine(config: SharedSyncConfig, log: PluginLogger): SharedSyncEngine;
442
1023
  //#endregion
443
- export { type AgentStats, type ApiClient, type ApiClientConfig, type ConfirmResult, type DownloadResult, type FileHistoryEntry, type LocalManifest, type ManifestDiff, type ManifestEntry, type PresignResult, type ReconstructResult, type RegisterAgentResult, type RemoteManifest, type SharedScope, type SharedSyncConfig, type SharedSyncEngine, type SyncConfig, type SyncEngine, type SyncPluginConfig, type SyncResult, type UploadResult, type WatcherOptions, computeFileHash, createApiClient, createSharedSyncEngine, createSyncEngine, diffManifests, downloadFiles, filterIgnored, invalidateSyncConfigCache, isInitialized, loadIgnorePatterns, plugin, readManifest, removeManifestEntry, requireConfig, resolveSyncConfig, shouldIgnore, startWatcher, syncStateDir, updateManifestEntry, uploadFiles, writeManifest };
1024
+ export { type DownloadResult, type LocalManifest, type ManifestDiff, type ManifestEntry, type RemoteManifest, type RetryOptions, type SharedScope, type SharedSyncConfig, type SharedSyncEngine, type SyncEngine, type SyncPluginConfig, type SyncResult, type UploadResult, type WatcherOptions, computeFileHash, createSharedSyncEngine, createSyncEngine, diffManifests, downloadFiles, filterIgnored, loadIgnorePatterns, plugin, readManifest, removeManifestEntry, shouldIgnore, startWatcher, updateManifestEntry, uploadFiles, withRetry, writeManifest };
444
1025
  //# sourceMappingURL=index.d.ts.map