@alfe.ai/openclaw-sync 0.0.16 → 0.0.18

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,1004 @@ 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
+ /**
236
+ * Display/validation hint for a field's value. `"json"` signals that the
237
+ * string is a JSON-stringified payload that consumers should `JSON.parse`.
238
+ */
239
+ declare const FIELD_FORMATS: readonly ["text", "email", "url", "phone", "date", "number", "json"];
240
+ type FieldFormat = (typeof FIELD_FORMATS)[number];
241
+ /**
242
+ * Whether a field is stored in plaintext (visible to anyone with read access)
243
+ * or encrypted (requires KMS + the right encryption context to read).
244
+ */
245
+ declare const FIELD_SENSITIVITIES: readonly ["plaintext", "encrypted"];
246
+ type FieldSensitivity = (typeof FIELD_SENSITIVITIES)[number];
247
+ /**
248
+ * A field on a secret. `value` is always a string at the wire; for encrypted
249
+ * fields it's the plaintext at the API edge (the service encrypts before
250
+ * persistence). Reads from the dashboard omit `value` for encrypted fields;
251
+ * agents get a `FieldEnvelope` instead and decrypt locally.
252
+ */
253
+
254
+ /**
255
+ * Secret category — drives icon/template/filter behaviour. Defaults to
256
+ * `"other"` for migrated rows.
257
+ */
258
+ declare const SECRET_CATEGORIES: readonly ["login", "api_key", "database", "ssh_key", "certificate", "secure_note", "credit_card", "identity", "wifi", "other"];
259
+ type SecretCategory = (typeof SECRET_CATEGORIES)[number];
260
+ /**
261
+ * One field as exposed to readers. Encrypted fields have no `value` on the
262
+ * dashboard read path; the agent-side aggregate carries `envelope` instead.
263
+ */
264
+ interface FieldView {
265
+ key: string;
266
+ format?: FieldFormat;
267
+ sensitivity: FieldSensitivity;
268
+ /** Present for `sensitivity: "plaintext"` only. */
269
+ value?: string;
270
+ /** Present for `sensitivity: "encrypted"` on agent-side reads only. */
271
+ envelope?: EncryptedEnvelopeV1;
272
+ /** Plaintext fields that opt into `format: "json"` are pre-parsed for callers. */
273
+ parsedValue?: unknown;
274
+ rotatedAt?: string;
275
+ createdAt: string;
276
+ updatedAt: string;
277
+ }
278
+ /** A secret as assembled from its multi-row aggregate. */
279
+ interface SecretAggregate {
280
+ secretId: string;
281
+ secretName: string;
282
+ description?: string;
283
+ tags: string[];
284
+ category: SecretCategory;
285
+ fields: FieldView[];
286
+ changelogVersion: number;
287
+ createdAt: string;
288
+ updatedAt: string;
289
+ }
290
+ /** Metadata-only projection — used by list endpoints. */
291
+ interface SecretMetadata {
292
+ secretId: string;
293
+ secretName: string;
294
+ description?: string;
295
+ tags: string[];
296
+ category: SecretCategory;
297
+ fieldKeys: string[];
298
+ changelogVersion: number;
299
+ createdAt: string;
300
+ updatedAt: string;
301
+ }
302
+ /**
303
+ * Per-field encrypted envelope returned to agents on the agent-side aggregate.
304
+ * Agents decrypt locally using a data key fetched from `/decrypt-data-key`.
305
+ */
306
+ interface FieldEnvelope {
307
+ key: string;
308
+ format?: FieldFormat;
309
+ envelope: EncryptedEnvelopeV1;
310
+ rotatedAt?: string;
311
+ createdAt: string;
312
+ updatedAt: string;
313
+ }
314
+ /** A scope the caller can read or write secrets in. */
315
+ interface ScopeInfo {
316
+ scope: SecretScope;
317
+ scopeId: string;
318
+ name?: string;
319
+ }
320
+ /**
321
+ * KMS-issued data key, returned by the secrets service's
322
+ * `/secrets/generate-data-key` KMS proxy endpoint. The plaintext key is
323
+ * returned base64-encoded; callers MUST decode it to a Buffer and zero the
324
+ * Buffer after use — never keep the plaintext as a JS string.
325
+ */
326
+ interface GeneratedDataKey {
327
+ plaintextKey: string;
328
+ dataKeyCiphertext: string;
329
+ }
330
+ /**
331
+ * Action types recorded in the secret changelog. Append-only.
332
+ */
333
+ declare const CHANGELOG_ACTIONS: readonly ["created", "deleted", "metadata_updated", "field_added", "field_rotated", "field_removed", "tag_added", "tag_removed"];
334
+ type ChangelogAction = (typeof CHANGELOG_ACTIONS)[number];
335
+ /** Who triggered a changelog entry. */
336
+ interface ChangelogActor {
337
+ kind: "user" | "agent" | "system";
338
+ id: string;
339
+ }
340
+ /**
341
+ * One audit row from the secret's changelog. Metadata only — never carries
342
+ * field VALUES (old or new). Rolling back a rotated secret is intentionally
343
+ * not supported.
344
+ */
345
+ interface ChangelogEntry {
346
+ changelogVersion: number;
347
+ action: ChangelogAction;
348
+ fieldKey?: string;
349
+ fieldSensitivity?: FieldSensitivity;
350
+ changedBy: ChangelogActor;
351
+ reason?: string;
352
+ timestamp: string;
353
+ }
354
+ //# sourceMappingURL=secrets.d.ts.map
355
+ //#endregion
356
+ //#region src/index.d.ts
357
+ interface AgentApiClientConfig {
358
+ apiKey: string;
158
359
  apiUrl: string;
159
- token: string;
360
+ }
361
+ interface SyncAgentInfo {
160
362
  agentId: string;
363
+ tenantId: string;
364
+ displayName: string;
365
+ s3Prefix: string;
366
+ status: "stale" | "syncing" | "synced";
367
+ fileCount?: number;
368
+ totalSize?: number;
369
+ lastSync?: string;
161
370
  }
162
- interface PresignResult {
163
- path: string;
164
- url: string;
165
- expiresAt: string;
371
+ interface SyncManifestEntry {
372
+ hash: string;
373
+ size: number;
374
+ modified: string;
375
+ etag?: string;
376
+ storageClass?: string;
377
+ compressed?: boolean;
166
378
  }
167
- interface AgentStats {
379
+ interface SyncManifest {
380
+ version: 1;
168
381
  agentId: string;
169
- standardBytes: number;
170
- glacierBytes: number;
171
- fileCount: number;
172
- lastSyncAt: string | null;
382
+ lastSync: string;
383
+ files: Record<string, SyncManifestEntry>;
173
384
  }
174
- interface RegisterAgentResult {
175
- agent: {
176
- agentId: string;
177
- orgId: string;
178
- displayName: string;
179
- status: string;
180
- createdAt: string;
181
- };
385
+ interface SyncPresignedUrl {
386
+ path: string;
387
+ url: string;
388
+ expiresAt: string;
182
389
  }
183
- interface ConfirmResult {
390
+ interface SyncConfirmedUpload {
184
391
  filePath: string;
185
392
  hash: string;
186
393
  size: number;
187
- storageClass: string;
394
+ storageClass: "STANDARD" | "GLACIER_IR";
188
395
  syncedAt: string;
189
396
  }
190
- interface ReconstructResult {
397
+ interface SyncReconstructFile {
398
+ path: string;
399
+ size: number;
400
+ url: string;
401
+ storageClass?: string;
402
+ compressed?: boolean;
403
+ }
404
+ interface SyncReconstructBundle {
191
405
  agentId: string;
192
406
  mode: "full" | "active" | "memory";
193
407
  fileCount: number;
194
408
  totalSize: number;
195
- files: {
196
- path: string;
197
- url: string;
198
- size: number;
199
- compressed: boolean;
200
- expiresAt: string;
201
- }[];
202
- generatedAt: string;
409
+ files: SyncReconstructFile[];
203
410
  expiresAt: string;
204
411
  }
205
- interface FileHistoryEntry {
206
- versionId: string;
207
- isLatest: boolean;
412
+ interface SyncAgentStats {
413
+ agentId: string;
414
+ standardBytes: number;
415
+ glacierBytes: number;
416
+ fileCount: number;
417
+ lastSyncAt: string | null;
418
+ }
419
+ interface SyncFileEntry {
420
+ filePath: string;
421
+ size: number;
422
+ modified: string;
423
+ contentHash: string;
424
+ storageClass?: string;
425
+ compressed?: boolean;
426
+ }
427
+ interface SyncSessionEntry {
428
+ sessionId: string;
429
+ size: number;
208
430
  lastModified: string;
431
+ storageClass?: string;
432
+ isArchived: boolean;
433
+ }
434
+ interface SyncSessionContent {
435
+ sessionId: string;
436
+ content: string;
437
+ compressed: boolean;
438
+ }
439
+ interface SharedFileEntry {
440
+ filePath: string;
441
+ fileName: string;
209
442
  size: number;
210
- etag?: string;
443
+ contentType?: string;
211
444
  }
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>;
445
+ declare class AgentApiClient {
446
+ private readonly apiKey;
447
+ private readonly apiUrl;
448
+ constructor(config: AgentApiClientConfig);
449
+ private request;
450
+ syncRegister(args?: {
451
+ displayName?: string;
452
+ }): Promise<{
453
+ agent: SyncAgentInfo;
454
+ }>;
455
+ syncGetManifest(): Promise<SyncManifest>;
456
+ syncPresign(args: {
457
+ files: {
458
+ path: string;
459
+ operation: "put" | "get";
460
+ contentType?: string;
461
+ }[];
462
+ }): Promise<{
463
+ urls: SyncPresignedUrl[];
464
+ }>;
465
+ syncConfirmUpload(args: {
466
+ filePath: string;
467
+ hash: string;
468
+ size: number;
469
+ storageClass?: "STANDARD" | "GLACIER_IR";
470
+ }): Promise<SyncConfirmedUpload>;
471
+ syncReconstruct(args: {
472
+ mode: "full" | "active" | "memory";
473
+ }): Promise<SyncReconstructBundle>;
474
+ syncGetStats(): Promise<SyncAgentStats>;
475
+ syncListFiles(args?: {
476
+ prefix?: string;
477
+ }): Promise<{
478
+ files: SyncFileEntry[];
479
+ }>;
480
+ syncListSessions(): Promise<{
481
+ sessions: SyncSessionEntry[];
482
+ }>;
483
+ syncGetSession(sessionId: string): Promise<SyncSessionContent>;
484
+ syncDeleteFile(filePath: string): Promise<{
485
+ removed: boolean;
486
+ }>;
487
+ sharedListFiles(args: {
488
+ scope: "org" | "team" | "project";
489
+ scopeId: string;
490
+ }): Promise<{
491
+ files: SharedFileEntry[];
492
+ nextCursor: string | null;
493
+ }>;
494
+ sharedDownloadUrl(args: {
495
+ scope: "org" | "team" | "project";
496
+ scopeId: string;
497
+ filePath: string;
498
+ }): Promise<{
499
+ downloadUrl: string;
500
+ expiresIn: number;
501
+ }>;
502
+ listIntegrations(): Promise<IntegrationInstall[]>;
503
+ getIntegrationConfig(integrationId: string): Promise<IntegrationConfigResult>;
504
+ updateIntegrationConfig(integrationId: string, config: Record<string, unknown>): Promise<void>;
505
+ installIntegration(integrationId: string, options?: {
506
+ version?: string;
507
+ config?: Record<string, unknown>;
508
+ }): Promise<IntegrationInstall>;
509
+ removeIntegration(integrationId: string): Promise<IntegrationInstall>;
510
+ getOAuthUrl(provider: string, scopes?: string[]): Promise<{
511
+ url: string;
512
+ provider: string;
513
+ expiresIn: number;
514
+ }>;
515
+ getOAuthStatus(provider: string): Promise<{
516
+ provider: string;
517
+ connected: boolean;
518
+ config?: Record<string, string>;
519
+ }>;
520
+ getRegistry(): Promise<{
521
+ integrations: RegistryEntry[];
522
+ }>;
523
+ getGoogleCredentials(): Promise<{
524
+ accounts?: {
525
+ email: string;
526
+ refreshToken: string;
527
+ clientId: string;
528
+ clientSecret: string;
529
+ enabledServices?: string[];
530
+ isDefault: boolean;
531
+ displayName?: string;
532
+ }[];
533
+ email: string;
534
+ refreshToken: string;
535
+ clientId: string;
536
+ clientSecret: string;
537
+ projectId: string;
538
+ enabledServices?: string[];
539
+ }>;
540
+ disconnectGoogleAccount(email: string): Promise<{
541
+ accounts: {
542
+ email: string;
543
+ displayName?: string;
544
+ isDefault: boolean;
545
+ }[];
546
+ }>;
547
+ setDefaultGoogleAccount(email: string): Promise<{
548
+ accounts: {
549
+ email: string;
550
+ displayName?: string;
551
+ isDefault: boolean;
552
+ }[];
553
+ }>;
554
+ getGoogleChatCredentials(): Promise<{
555
+ email: string;
556
+ refreshToken: string;
557
+ clientId: string;
558
+ clientSecret: string;
559
+ displayName?: string;
560
+ }>;
561
+ getGithubCredentials(): Promise<{
562
+ login: string;
563
+ accessToken: string;
564
+ }>;
565
+ getXeroCredentials(): Promise<{
566
+ accessToken: string;
567
+ accessTokenExpiresAt: string;
568
+ xeroTenantId: string;
569
+ }>;
570
+ refreshXeroToken(): Promise<{
571
+ accessToken: string;
572
+ expiresAt: string;
573
+ }>;
574
+ getNotionCredentials(): Promise<{
575
+ accessToken: string;
576
+ workspaceId: string;
577
+ workspaceName: string;
578
+ }>;
579
+ getAtlassianCredentials(): Promise<{
580
+ accessToken: string;
581
+ refreshToken: string;
582
+ accessTokenExpiresAt: string;
583
+ cloudId: string;
584
+ siteName: string;
585
+ siteUrl: string;
586
+ email: string;
587
+ enabledProducts: string[];
588
+ clientId: string;
589
+ clientSecret: string;
590
+ }>;
591
+ refreshAtlassianToken(): Promise<{
592
+ accessToken: string;
593
+ expiresAt: string;
594
+ }>;
595
+ getMYOBCredentials(): Promise<{
596
+ accessToken: string;
597
+ accessTokenExpiresAt: string;
598
+ myobBusinessId: string;
599
+ clientId: string;
600
+ }>;
601
+ refreshMYOBToken(): Promise<{
602
+ accessToken: string;
603
+ expiresAt: string;
604
+ }>;
605
+ getTeamsCredentials(): Promise<{
606
+ agentId: string;
607
+ tenantId: string;
608
+ azureAppId: string;
609
+ azureBotId: string;
610
+ azureClientSecret: string;
611
+ botDisplayName?: string;
612
+ teamsTenantId?: string;
613
+ serviceUrl?: string;
614
+ }>;
615
+ sendTeamsMessage(data: {
616
+ conversationId: string;
617
+ text?: string;
618
+ adaptiveCard?: Record<string, unknown>;
619
+ }): Promise<{
620
+ ok: boolean;
621
+ activityId: string;
622
+ }>;
623
+ listTeamsChannels(): Promise<{
624
+ channels: {
625
+ id: string;
626
+ name: string;
627
+ description?: string;
628
+ }[];
629
+ }>;
630
+ presignAttachments(files: {
631
+ filename: string;
632
+ mimeType: string;
633
+ size: number;
634
+ }[]): Promise<{
635
+ attachments: {
636
+ id: string;
637
+ uploadUrl: string;
638
+ downloadUrl: string;
639
+ s3Key: string;
640
+ expiresAt: string;
641
+ }[];
642
+ }>;
643
+ recordActivity(data: {
644
+ userId?: string;
645
+ channel: string;
646
+ role: "user" | "assistant";
647
+ }): Promise<{
648
+ recorded: boolean;
649
+ }>;
239
650
  /**
240
- * Request presigned GET URLs for multiple files.
651
+ * Mint a fresh AES-256 data key for a specific (secret, field) pair. The
652
+ * encryption context is rebuilt server-side from `auth.tenantId` + the body
653
+ * fields including `fieldKey`; the agent cannot forge context for a scope
654
+ * or field it doesn't own. Legacy single-envelope secrets are migrated to
655
+ * `field#value` rows by the data migration, so call with `fieldKey: "value"`
656
+ * to reach them.
241
657
  */
242
- presignGetBatch(paths: string[]): Promise<PresignResult[]>;
658
+ generateSecretDataKey(args: {
659
+ scope: SecretScope;
660
+ scopeId: string;
661
+ secretId: string;
662
+ fieldKey: string;
663
+ }): Promise<GeneratedDataKey>;
243
664
  /**
244
- * Get agent storage stats.
665
+ * Unwrap a wrapped data key so the agent can decrypt the envelope locally.
666
+ * `fieldKey` MUST match the value supplied when the data key was generated
667
+ * (it's bound into KMS encryption context); mismatch fails with
668
+ * `InvalidCiphertextException`.
245
669
  */
246
- getStats(): Promise<AgentStats>;
670
+ decryptSecretDataKey(args: {
671
+ scope: SecretScope;
672
+ scopeId: string;
673
+ secretId: string;
674
+ fieldKey: string;
675
+ dataKeyCiphertext: string;
676
+ }): Promise<{
677
+ plaintextKey: string;
678
+ }>;
247
679
  /**
248
- * Register this agent with the sync service.
680
+ * Create a new secret with one or more fields. Encrypted fields must arrive
681
+ * pre-sealed (the agent has already obtained per-field data keys via
682
+ * `generateSecretDataKey({ ..., fieldKey })` and AES-encrypted locally).
683
+ * Plaintext fields ship the value inline.
249
684
  */
250
- registerAgent(displayName?: string): Promise<RegisterAgentResult>;
685
+ createSecret(args: {
686
+ scope: SecretScope;
687
+ scopeId: string;
688
+ secretId: string;
689
+ secretName: string;
690
+ category?: SecretCategory;
691
+ description?: string;
692
+ tags?: string[];
693
+ fields: {
694
+ key: string;
695
+ format?: FieldFormat;
696
+ sensitivity: FieldSensitivity;
697
+ value?: string;
698
+ envelope?: EncryptedEnvelopeV1;
699
+ }[];
700
+ reason?: string;
701
+ }): Promise<SecretAggregate>;
702
+ /** Fetch the secret aggregate plus per-field encrypted envelopes. */
703
+ getSecret(args: {
704
+ scope: SecretScope;
705
+ scopeId: string;
706
+ secretId: string;
707
+ }): Promise<{
708
+ aggregate: SecretAggregate;
709
+ envelopes: FieldEnvelope[];
710
+ }>;
711
+ /** Fetch one field. Plaintext: value inline. Encrypted: envelope. */
712
+ getSecretField(args: {
713
+ scope: SecretScope;
714
+ scopeId: string;
715
+ secretId: string;
716
+ fieldKey: string;
717
+ }): Promise<{
718
+ key: string;
719
+ sensitivity: FieldSensitivity;
720
+ format?: FieldFormat;
721
+ value?: string;
722
+ envelope?: EncryptedEnvelopeV1;
723
+ rotatedAt?: string;
724
+ createdAt: string;
725
+ updatedAt: string;
726
+ }>;
727
+ /** Add OR rotate one field. */
728
+ setSecretField(args: {
729
+ scope: SecretScope;
730
+ scopeId: string;
731
+ secretId: string;
732
+ fieldKey: string;
733
+ sensitivity: FieldSensitivity;
734
+ format?: FieldFormat;
735
+ value?: string;
736
+ envelope?: EncryptedEnvelopeV1;
737
+ reason?: string;
738
+ }): Promise<{
739
+ fieldKey: string;
740
+ rotated: boolean;
741
+ }>;
742
+ /** Remove one field. */
743
+ removeSecretField(args: {
744
+ scope: SecretScope;
745
+ scopeId: string;
746
+ secretId: string;
747
+ fieldKey: string;
748
+ }): Promise<void>;
749
+ /** Update secret-level metadata (name/description/tags/category). */
750
+ updateSecretMetadata(args: {
751
+ scope: SecretScope;
752
+ scopeId: string;
753
+ secretId: string;
754
+ secretName?: string;
755
+ description?: string;
756
+ tags?: string[];
757
+ category?: SecretCategory;
758
+ reason?: string;
759
+ }): Promise<SecretAggregate>;
760
+ /** List metadata for secrets in a scope. Optional filters route through the byFacet GSI. */
761
+ listSecrets(args: {
762
+ scope: SecretScope;
763
+ scopeId: string;
764
+ category?: SecretCategory;
765
+ tag?: string;
766
+ fieldKey?: string;
767
+ }): Promise<SecretMetadata[]>;
768
+ /** Bounded changelog read — metadata-only audit entries. */
769
+ getSecretHistory(args: {
770
+ scope: SecretScope;
771
+ scopeId: string;
772
+ secretId: string;
773
+ limit?: number;
774
+ cursor?: string;
775
+ }): Promise<{
776
+ entries: ChangelogEntry[];
777
+ nextCursor?: string;
778
+ }>;
779
+ /** Delete a secret (and all its field rows + tag rows + changelog rows). */
780
+ deleteSecret(args: {
781
+ scope: SecretScope;
782
+ scopeId: string;
783
+ secretId: string;
784
+ }): Promise<void>;
785
+ /** Enumerate scopes (org/team/project/agent) this agent can access. */
786
+ listSecretScopes(): Promise<ScopeInfo[]>;
787
+ resolveIdentity(args: {
788
+ provider: string;
789
+ platformId: string;
790
+ kind?: "user" | "agent" | "service" | "bot" | "workspace";
791
+ displayName?: string;
792
+ }): Promise<{
793
+ identityId: string | null;
794
+ status: string;
795
+ accessAllowed: boolean;
796
+ created?: boolean;
797
+ reason?: string;
798
+ }>;
799
+ searchIdentities(args?: {
800
+ q?: string;
801
+ status?: string;
802
+ limit?: number;
803
+ }): Promise<{
804
+ identities: unknown[];
805
+ }>;
806
+ getIdentityContext(identityId: string): Promise<{
807
+ context: unknown;
808
+ }>;
809
+ mergeIdentities(survivorId: string, args: {
810
+ mergedId: string;
811
+ changedBy: {
812
+ type: string;
813
+ id: string;
814
+ name?: string;
815
+ };
816
+ }): Promise<{
817
+ ok: boolean;
818
+ error?: string;
819
+ }>;
820
+ unmergeIdentity(identityId: string, args: {
821
+ changedBy: {
822
+ type: string;
823
+ id: string;
824
+ name?: string;
825
+ };
826
+ }): Promise<{
827
+ ok: boolean;
828
+ error?: string;
829
+ }>;
830
+ addIdentityNote(identityId: string, args: {
831
+ content: string;
832
+ category?: string;
833
+ changedBy: {
834
+ type: string;
835
+ id: string;
836
+ name?: string;
837
+ };
838
+ }): Promise<{
839
+ noteId: string | null;
840
+ }>;
841
+ tagIdentity(identityId: string, args: {
842
+ tag: string;
843
+ action: "add" | "remove";
844
+ changedBy: {
845
+ type: string;
846
+ id: string;
847
+ name?: string;
848
+ };
849
+ }): Promise<{
850
+ ok: boolean;
851
+ }>;
852
+ getIdentityChangelog(identityId: string, args?: {
853
+ limit?: number;
854
+ }): Promise<{
855
+ entries: unknown[];
856
+ }>;
857
+ rollbackIdentity(identityId: string, args: {
858
+ targetVersion: number;
859
+ changedBy: {
860
+ type: string;
861
+ id: string;
862
+ name?: string;
863
+ };
864
+ }): Promise<{
865
+ ok: boolean;
866
+ entry?: unknown;
867
+ }>;
868
+ requestIdentityVerification(args: {
869
+ claimedIdentityId: string;
870
+ requestingIdentityId: string;
871
+ requestingProvider: string;
872
+ requestingPlatformId: string;
873
+ preferredChannel?: "mobile" | "email";
874
+ /**
875
+ * Phase 2: agent-supplied contact endpoint. When provided, the top-level
876
+ * `preferredChannel` is ignored — the contact's channel wins.
877
+ */
878
+ contact?: {
879
+ channel: "email" | "mobile";
880
+ value: string;
881
+ };
882
+ }): Promise<{
883
+ verificationId: string;
884
+ channel: string;
885
+ deliveredTo: string;
886
+ expiresAt: string;
887
+ availableChannels: {
888
+ channel: string;
889
+ deliveredTo: string;
890
+ }[];
891
+ } | {
892
+ error: string;
893
+ }>;
894
+ confirmIdentityVerification(args: {
895
+ claimedIdentityId: string;
896
+ verificationId: string;
897
+ phrase: string;
898
+ }): Promise<{
899
+ verified: boolean;
900
+ identityId?: string;
901
+ /** Phase 2: how the confirm resolved — Scenario A vs B. */
902
+ action?: "merged" | "contact_verified";
903
+ error?: string;
904
+ }>;
251
905
  /**
252
- * Get file version history.
906
+ * Update display-shape fields on an Identity. Body excludes `email` /
907
+ * `phone` / `title` / `company` / `metadata` per Section D4 — contacts go
908
+ * via the verify flow, title/company live on OrgMembership, metadata is
909
+ * not agent-writable.
253
910
  */
254
- getFileHistory(filePath: string): Promise<FileHistoryEntry[]>;
911
+ updateIdentity(identityId: string, args: {
912
+ name?: string;
913
+ avatarUrl?: string;
914
+ timezone?: string;
915
+ locale?: string;
916
+ }): Promise<{
917
+ ok: boolean;
918
+ }>;
255
919
  /**
256
- * Generate a reconstruction bundle.
920
+ * Phase 2 (Section H): server-side verification of a Google Chat sender via
921
+ * the agent's existing Google OAuth credentials. Returns the resolved
922
+ * identity (created or matched via Scenario-B email enrichment).
257
923
  */
258
- reconstruct(mode?: "full" | "active" | "memory"): Promise<ReconstructResult>;
259
- };
260
- type ApiClient = ReturnType<typeof createApiClient>;
261
- //# sourceMappingURL=api-client.d.ts.map
924
+ resolveGoogleChatSender(args: {
925
+ senderUserId: string;
926
+ spaceId?: string;
927
+ }): Promise<{
928
+ identityId: string | null;
929
+ status: string;
930
+ accessAllowed: boolean;
931
+ }>;
932
+ memorySearch(query: string, opts?: {
933
+ limit?: number;
934
+ topic?: string;
935
+ subtopic?: string;
936
+ tag?: string;
937
+ includeKnowledge?: boolean;
938
+ }): Promise<{
939
+ facts: {
940
+ subject: string;
941
+ predicate: string;
942
+ object: string;
943
+ since: string;
944
+ confidence: number;
945
+ }[];
946
+ memories: {
947
+ id: string;
948
+ text: string;
949
+ topic: string;
950
+ subtopic: string;
951
+ tag: string;
952
+ importance: number;
953
+ timestamp: number;
954
+ score: number;
955
+ }[];
956
+ }>;
957
+ memoryStore(text: string, opts?: {
958
+ topic?: string;
959
+ subtopic?: string;
960
+ tag?: string;
961
+ importance?: number;
962
+ }): Promise<{
963
+ memoryId: string;
964
+ }>;
965
+ memoryIngest(sessionKey: string, messages: {
966
+ role: string;
967
+ content: string;
968
+ index: number;
969
+ timestamp?: string;
970
+ }[], metadata?: {
971
+ channelId?: string;
972
+ userId?: string;
973
+ userName?: string;
974
+ }): Promise<{
975
+ queued: boolean;
976
+ messageCount: number;
977
+ }>;
978
+ memoryLoadContext(tier?: number, topicHint?: string): Promise<{
979
+ formatted: string;
980
+ [key: string]: unknown;
981
+ }>;
982
+ memoryLookupEntity(subject: string): Promise<{
983
+ subject: string;
984
+ triples: {
985
+ tripleId: string;
986
+ predicate: string;
987
+ object: string;
988
+ validFrom: string;
989
+ validTo?: string;
990
+ confidence: number;
991
+ }[];
992
+ }>;
993
+ memoryNavigate(): Promise<{
994
+ topics: {
995
+ name: string;
996
+ tripleCount: number;
997
+ subtopics: string[];
998
+ }[];
999
+ cursor: string | null;
1000
+ }>;
1001
+ memoryDelete(memoryId: string): Promise<{
1002
+ deleted: boolean;
1003
+ }>;
1004
+ memoryStats(): Promise<{
1005
+ vectorCount: number;
1006
+ tripleCount: number;
1007
+ storageEstimateBytes: number;
1008
+ lastIngestionAt?: string;
1009
+ }>;
1010
+ searchWeb(params: {
1011
+ query: string;
1012
+ count?: number;
1013
+ offset?: number;
1014
+ country?: string;
1015
+ freshness?: string;
1016
+ }): Promise<unknown>;
1017
+ searchImages(params: {
1018
+ query: string;
1019
+ count?: number;
1020
+ }): Promise<unknown>;
1021
+ searchNews(params: {
1022
+ query: string;
1023
+ count?: number;
1024
+ freshness?: string;
1025
+ }): Promise<unknown>;
1026
+ registerDatabaseCredentials(): Promise<{
1027
+ connectionString: string;
1028
+ username: string;
1029
+ password: string;
1030
+ databases: string[];
1031
+ }>;
1032
+ reportDatabaseAudit(entry: {
1033
+ database: string;
1034
+ collection: string;
1035
+ operation: string;
1036
+ summary?: string;
1037
+ }): Promise<void>;
1038
+ }
1039
+ //# sourceMappingURL=index.d.ts.map
1040
+ //#endregion
262
1041
  //#endregion
263
1042
  //#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
1043
  interface SyncResult {
276
1044
  pushed: number;
277
1045
  pulled: number;
278
1046
  conflicts: number;
279
1047
  errors: number;
280
1048
  }
1049
+ interface SyncEngineOptions {
1050
+ workspacePath: string;
1051
+ client: AgentApiClient;
1052
+ }
281
1053
  /**
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).
1054
+ * Construct a sync engine bound to a workspace + agent API client.
1055
+ *
1056
+ * The client is constructed once in plugin.ts (or the CLI) and passed in,
1057
+ * so credentials never leak into multiple places.
284
1058
  */
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
- };
1059
+ declare function createSyncEngine({
1060
+ workspacePath,
1061
+ client
1062
+ }: SyncEngineOptions): {
1063
+ workspacePath: string;
1064
+ client: AgentApiClient;
302
1065
  /**
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.
1066
+ * Upload changed files. Pass `paths` for an explicit list, or omit
1067
+ * to scan the workspace for anything that drifted from the manifest.
307
1068
  */
308
1069
  push(paths?: string[], options?: {
309
1070
  quiet?: boolean;
310
1071
  filter?: string;
311
1072
  }): Promise<SyncResult>;
312
- /**
313
- * Pull files from remote that are newer than local.
314
- */
1073
+ /** Download files newer on remote. */
315
1074
  pull(options?: {
316
1075
  quiet?: boolean;
317
1076
  }): Promise<SyncResult>;
318
1077
  /**
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.
1078
+ * Bidirectional sync. True conflicts (changed on both sides) are saved
1079
+ * locally as `.conflict-<ts>` files and the remote version wins.
324
1080
  */
325
1081
  fullSync(options?: {
326
1082
  quiet?: boolean;
327
1083
  }): Promise<SyncResult>;
328
1084
  /**
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.
1085
+ * Pull a known list of files (used for relay-driven notifications,
1086
+ * where we already know which paths changed remotely).
333
1087
  */
334
1088
  pullFiles(paths: string[], options?: {
335
1089
  quiet?: boolean;
336
1090
  }): Promise<SyncResult>;
337
1091
  /**
338
- * Remove a file locally and from the manifest.
339
- *
340
- * Used for notification-driven deletes when a remote file is removed.
1092
+ * Delete a file locally and from the manifest. Used when the sync relay
1093
+ * tells us a file was removed remotely.
341
1094
  */
342
1095
  removeLocalFile(filePath: string, options?: {
343
1096
  quiet?: boolean;
344
1097
  }): Promise<void>;
345
- }>;
346
- type SyncEngine = Awaited<ReturnType<typeof createSyncEngine>>;
1098
+ };
1099
+ type SyncEngine = ReturnType<typeof createSyncEngine>;
347
1100
  //# sourceMappingURL=sync-engine.d.ts.map
348
1101
  //#endregion
349
1102
  //#region src/watcher.d.ts
@@ -377,11 +1130,9 @@ interface UploadResult {
377
1130
  error?: string;
378
1131
  }
379
1132
  /**
380
- * Upload multiple files to S3.
381
- *
382
- * Uploads are performed in parallel with a concurrency limit.
1133
+ * Upload many files, batched by `concurrency`.
383
1134
  */
384
- declare function uploadFiles(workspacePath: string, relativePaths: string[], client: ApiClient, options?: {
1135
+ declare function uploadFiles(workspacePath: string, relativePaths: string[], client: AgentApiClient, options?: {
385
1136
  concurrency?: number;
386
1137
  quiet?: boolean;
387
1138
  }): Promise<UploadResult[]>;
@@ -394,26 +1145,30 @@ interface DownloadResult {
394
1145
  size?: number;
395
1146
  error?: string;
396
1147
  }
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?: {
1148
+ declare function downloadFiles(workspacePath: string, relativePaths: string[], client: AgentApiClient, remoteManifest?: RemoteManifest, options?: {
403
1149
  concurrency?: number;
404
1150
  quiet?: boolean;
405
1151
  }): Promise<DownloadResult[]>;
406
1152
  //# sourceMappingURL=downloader.d.ts.map
407
1153
  //#endregion
408
- //#region src/shared-sync.d.ts
1154
+ //#region src/retry.d.ts
409
1155
  /**
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.
1156
+ * Tiny retry helper used by uploader/downloader. Extracted so both
1157
+ * use the same timing and surface the same final error shape.
416
1158
  */
1159
+ interface RetryOptions {
1160
+ maxRetries?: number;
1161
+ baseDelayMs?: number;
1162
+ }
1163
+ /**
1164
+ * Run `fn` up to `maxRetries + 1` times with exponential backoff
1165
+ * (`base * 2^attempt`). Returns the first successful value, or rethrows
1166
+ * the last error.
1167
+ */
1168
+ declare function withRetry<T>(fn: () => Promise<T>, options?: RetryOptions): Promise<T>;
1169
+ //# sourceMappingURL=retry.d.ts.map
1170
+ //#endregion
1171
+ //#region src/shared-sync.d.ts
417
1172
  interface SharedScope {
418
1173
  scopeType: "team" | "project" | "org";
419
1174
  scopeId: string;
@@ -421,9 +1176,7 @@ interface SharedScope {
421
1176
  }
422
1177
  interface SharedSyncConfig {
423
1178
  workspacePath: string;
424
- apiUrl: string;
425
- token: string;
426
- agentId: string;
1179
+ client: AgentApiClient;
427
1180
  }
428
1181
  interface PluginLogger {
429
1182
  info(msg: string): void;
@@ -440,5 +1193,5 @@ interface SharedSyncEngine {
440
1193
  }
441
1194
  declare function createSharedSyncEngine(config: SharedSyncConfig, log: PluginLogger): SharedSyncEngine;
442
1195
  //#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 };
1196
+ 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
1197
  //# sourceMappingURL=index.d.ts.map