@fias/arche-sdk 2.3.0 → 2.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/dist/bridge.d.ts +76 -1
  2. package/dist/bridge.d.ts.map +1 -1
  3. package/dist/bridge.js +219 -6
  4. package/dist/bridge.js.map +1 -1
  5. package/dist/bridge.test.js +155 -6
  6. package/dist/bridge.test.js.map +1 -1
  7. package/dist/coverage-fills.test.js +26 -32
  8. package/dist/coverage-fills.test.js.map +1 -1
  9. package/dist/entity-ops.d.ts +55 -0
  10. package/dist/entity-ops.d.ts.map +1 -0
  11. package/dist/entity-ops.js +48 -0
  12. package/dist/entity-ops.js.map +1 -0
  13. package/dist/fias.d.ts +11 -1
  14. package/dist/fias.d.ts.map +1 -1
  15. package/dist/fias.js +39 -12
  16. package/dist/fias.js.map +1 -1
  17. package/dist/generated/permissions.d.ts +7 -1
  18. package/dist/generated/permissions.d.ts.map +1 -1
  19. package/dist/generated/permissions.js +35 -2
  20. package/dist/generated/permissions.js.map +1 -1
  21. package/dist/generated/surfaces.d.ts +424 -0
  22. package/dist/generated/surfaces.d.ts.map +1 -1
  23. package/dist/generated/surfaces.js +97 -1
  24. package/dist/generated/surfaces.js.map +1 -1
  25. package/dist/hooks.d.ts +228 -13
  26. package/dist/hooks.d.ts.map +1 -1
  27. package/dist/hooks.js +527 -104
  28. package/dist/hooks.js.map +1 -1
  29. package/dist/hooks.test.js +314 -247
  30. package/dist/hooks.test.js.map +1 -1
  31. package/dist/index.d.ts +4 -4
  32. package/dist/index.d.ts.map +1 -1
  33. package/dist/index.js +12 -2
  34. package/dist/index.js.map +1 -1
  35. package/dist/index.mjs +982 -115
  36. package/dist/protocol.d.ts +7 -0
  37. package/dist/protocol.d.ts.map +1 -1
  38. package/dist/protocol.js +7 -0
  39. package/dist/protocol.js.map +1 -1
  40. package/dist/provider.d.ts +50 -1
  41. package/dist/provider.d.ts.map +1 -1
  42. package/dist/provider.js +187 -2
  43. package/dist/provider.js.map +1 -1
  44. package/dist/provider.render.test.d.ts +17 -0
  45. package/dist/provider.render.test.d.ts.map +1 -0
  46. package/dist/provider.render.test.js +191 -0
  47. package/dist/provider.render.test.js.map +1 -0
  48. package/dist/provider.test.js +64 -8
  49. package/dist/provider.test.js.map +1 -1
  50. package/dist/types.d.ts +373 -27
  51. package/dist/types.d.ts.map +1 -1
  52. package/package.json +2 -1
  53. package/templates/default/AGENTS.md +321 -34
  54. package/templates/default/CLAUDE.md +321 -34
@@ -24,9 +24,17 @@ const MockProvider = jest.fn(({ children }) => children);
24
24
  jest.mock('./context', () => ({
25
25
  FiasBridgeContext: { Provider: MockProvider },
26
26
  }));
27
- // Capture React hook calls
28
- let capturedEffectCleanup = null;
27
+ // Capture React hook calls.
28
+ // UPDATED (Phase 6): the provider now has multiple effects (bridge init +
29
+ // unhandledrejection listener) — collect EVERY cleanup and run them all,
30
+ // instead of keeping only the last one (which silently pointed the old
31
+ // single-cleanup tests at whichever effect happened to run last).
32
+ let capturedEffectCleanups = [];
29
33
  const mockSetReady = jest.fn();
34
+ function runAllEffectCleanups() {
35
+ for (const cleanup of capturedEffectCleanups)
36
+ cleanup();
37
+ }
30
38
  jest.mock('react', () => {
31
39
  const actual = jest.requireActual('react');
32
40
  return {
@@ -36,7 +44,7 @@ jest.mock('react', () => {
36
44
  useEffect: jest.fn((cb) => {
37
45
  const cleanup = cb();
38
46
  if (typeof cleanup === 'function') {
39
- capturedEffectCleanup = cleanup;
47
+ capturedEffectCleanups.push(cleanup);
40
48
  }
41
49
  }),
42
50
  };
@@ -44,7 +52,7 @@ jest.mock('react', () => {
44
52
  describe('FiasProvider', () => {
45
53
  beforeEach(() => {
46
54
  jest.clearAllMocks();
47
- capturedEffectCleanup = null;
55
+ capturedEffectCleanups = [];
48
56
  mockBridge.waitForInit.mockResolvedValue(undefined);
49
57
  });
50
58
  it('uses getBridge() singleton via useMemo', () => {
@@ -66,8 +74,8 @@ describe('FiasProvider', () => {
66
74
  it('does NOT call bridge.destroy() on cleanup (StrictMode safety)', () => {
67
75
  const { FiasProvider } = require('./provider');
68
76
  FiasProvider({ children: null });
69
- expect(capturedEffectCleanup).toBeDefined();
70
- capturedEffectCleanup();
77
+ expect(capturedEffectCleanups.length).toBeGreaterThan(0);
78
+ runAllEffectCleanups();
71
79
  expect(mockBridge.destroy).not.toHaveBeenCalled();
72
80
  });
73
81
  it('does not call ready if unmounted before init resolves', async () => {
@@ -77,8 +85,8 @@ describe('FiasProvider', () => {
77
85
  }));
78
86
  const { FiasProvider } = require('./provider');
79
87
  FiasProvider({ children: null });
80
- // Run cleanup before init resolves (simulates unmount)
81
- capturedEffectCleanup();
88
+ // Run cleanups before init resolves (simulates unmount)
89
+ runAllEffectCleanups();
82
90
  resolveInit();
83
91
  await Promise.resolve();
84
92
  await Promise.resolve();
@@ -93,4 +101,52 @@ describe('FiasProvider', () => {
93
101
  expect(result).toBeNull();
94
102
  });
95
103
  });
104
+ describe('PluginErrorBoundary', () => {
105
+ beforeEach(() => {
106
+ jest.clearAllMocks();
107
+ });
108
+ it('getDerivedStateFromError captures the thrown error', () => {
109
+ const { PluginErrorBoundary } = require('./provider');
110
+ const err = new Error('Permission denied: user:profile:read not granted');
111
+ expect(PluginErrorBoundary.getDerivedStateFromError(err)).toEqual({ error: err });
112
+ });
113
+ it('renders children when there is no error', () => {
114
+ const { PluginErrorBoundary } = require('./provider');
115
+ const boundary = new PluginErrorBoundary({ children: 'the-app' });
116
+ boundary.state = { error: null, resetCount: 0 };
117
+ // UPDATED (Phase 6): children are wrapped in a keyed Fragment so a reset
118
+ // (key bump) remounts the crashed subtree instead of reusing its state.
119
+ const rendered = boundary.render();
120
+ expect(rendered.props.children).toBe('the-app');
121
+ expect(rendered.key).toBe('0');
122
+ });
123
+ it('renders the error screen (not children) once an error is captured', () => {
124
+ const { PluginErrorBoundary, FiasErrorScreen } = require('./provider');
125
+ const err = new Error('Permission denied: user:profile:read not granted');
126
+ const boundary = new PluginErrorBoundary({ children: 'the-app' });
127
+ boundary.state = { error: err, resetCount: 0 };
128
+ const rendered = boundary.render();
129
+ expect(rendered.type).toBe(FiasErrorScreen);
130
+ expect(rendered.props.error).toBe(err);
131
+ // The error screen gets a reset handler ("Try again").
132
+ expect(rendered.props.onReset).toBe(boundary.handleReset);
133
+ });
134
+ it('componentDidCatch logs instead of failing silently', () => {
135
+ const { PluginErrorBoundary } = require('./provider');
136
+ const spy = jest.spyOn(console, 'error').mockImplementation(() => { });
137
+ const boundary = new PluginErrorBoundary({ children: null });
138
+ const err = new Error('boom');
139
+ boundary.componentDidCatch(err, { componentStack: '\n at App' });
140
+ expect(spy).toHaveBeenCalledWith(expect.stringContaining('[fias-sdk]'), err, expect.any(String));
141
+ spy.mockRestore();
142
+ });
143
+ it('FiasErrorScreen surfaces the error message', () => {
144
+ const { FiasErrorScreen } = require('./provider');
145
+ const el = FiasErrorScreen({
146
+ error: new Error('Permission denied: user:profile:read not granted'),
147
+ });
148
+ expect(el.props.role).toBe('alert');
149
+ expect(JSON.stringify(el)).toContain('user:profile:read');
150
+ });
151
+ });
96
152
  //# sourceMappingURL=provider.test.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"provider.test.js","sourceRoot":"","sources":["../src/provider.test.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"provider.test.js","sourceRoot":"","sources":["../src/provider.test.ts"],"names":[],"mappings":"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"}
package/dist/types.d.ts CHANGED
@@ -95,6 +95,20 @@ export interface EntityInvocationApi {
95
95
  */
96
96
  streamingText: string;
97
97
  }
98
+ /**
99
+ * Client-side entity invocation API available via the `useClientEntity()`
100
+ * hook. The client-side counterpart to {@link EntityInvocationApi}: invokes
101
+ * an on-device entity (grammar check, background removal, …) by ID through
102
+ * the bridge's generic `client_entity_invoke` op. Requires the
103
+ * `entities:client_invoke` permission. The typed result flows back through
104
+ * the returned promise — supply the entity's input/output types at the call
105
+ * site, e.g. `invoke<GrammarCheckInput, GrammarCheckResult>(id, input)`.
106
+ */
107
+ export interface ClientEntityApi {
108
+ invoke: <TInput = unknown, TResult = unknown>(entityId: string, input: TInput) => Promise<TResult>;
109
+ isLoading: boolean;
110
+ error: Error | null;
111
+ }
98
112
  /**
99
113
  * How a plugin picks a text model for `useEntityInvocation({ entityId, ... })`:
100
114
  *
@@ -114,9 +128,27 @@ export type TextCapabilityId = 'text-fast' | 'text-standard' | 'text-advanced';
114
128
  export type TextEntitySelector = string | {
115
129
  capability: TextCapabilityId;
116
130
  };
131
+ /**
132
+ * An image sent to a vision-capable model alongside `input` (e.g. OCR,
133
+ * chart/figure understanding, visual Q&A). Base64-encoded bytes plus the MIME
134
+ * type — no `data:` prefix.
135
+ */
136
+ export interface EntityInvocationImage {
137
+ /** MIME type, e.g. `'image/jpeg'`, `'image/png'`, `'image/webp'`, `'image/gif'`. */
138
+ mediaType: string;
139
+ /** Base64-encoded image bytes, WITHOUT a `data:<type>;base64,` prefix. */
140
+ dataBase64: string;
141
+ }
117
142
  export interface EntityInvocationParams {
118
143
  entityId: TextEntitySelector;
119
144
  input: string;
145
+ /**
146
+ * Optional image inputs for a vision-capable model. The resolved model must
147
+ * support vision or the call is rejected. Sent together with `input` as a
148
+ * single user message. Billed like any other invocation (the 20% markup
149
+ * applies). Bounded per call — keep images small (downscale before sending).
150
+ */
151
+ images?: EntityInvocationImage[];
120
152
  parameters?: Record<string, unknown>;
121
153
  /** System prompt to send to the AI model. The arche/plugin provides context; the entity provides the capability. */
122
154
  systemPrompt?: string;
@@ -311,25 +343,86 @@ export interface ImageGenerationApi {
311
343
  error: Error | null;
312
344
  }
313
345
  /**
314
- * Result of background removal via the `client_entity_invoke` bridge op
315
- * targeting the imgly background-removal entity. A transparent PNG.
346
+ * Parameters for on-device translation via the `client_entity_invoke` bridge
347
+ * op targeting the NLLB-200 translation entity.
348
+ */
349
+ export interface TranslateParams {
350
+ /** Text to translate. */
351
+ text: string;
352
+ /**
353
+ * Target language as a FLORES-200 code (e.g. `'fra_Latn'`). Pick from
354
+ * `NLLB_LANGUAGES` for a ready-made label/code list.
355
+ */
356
+ targetLang: string;
357
+ /**
358
+ * Source language as a FLORES-200 code. Omit to auto-detect on-device.
359
+ * Supplying it skips detection (faster; avoids misdetection on short text).
360
+ */
361
+ sourceLang?: string;
362
+ }
363
+ /**
364
+ * Result of on-device translation. Produced entirely in the host page by a
365
+ * WASM model — text never leaves the user's device.
366
+ */
367
+ export interface TranslationResult {
368
+ /** The translated text. */
369
+ translation: string;
370
+ /** The FLORES-200 source code actually used (detected, or the one passed in). */
371
+ detectedSourceLang: string;
372
+ }
373
+ /**
374
+ * Issue categories surfaced by the grammar_check client-side entity.
316
375
  *
317
- * The blob is processed entirely in the host page using a WASM/ONNX model —
318
- * bytes never leave the user's device. Inputs are capped at 25 MiB
319
- * (26,214,400 bytes); larger inputs reject with an error.
376
+ * NOTE: duplicated from the executor's type (the SDK is dependency-free and
377
+ * cannot import from the platform client). Kept in lockstep by review.
320
378
  */
321
- export interface ImageRemoveBackgroundResult {
322
- image: Blob;
379
+ export type GrammarCategory = 'spelling' | 'grammar' | 'style' | 'readability';
380
+ /** A single grammar/spelling/style/readability issue. */
381
+ export interface GrammarIssue {
382
+ /** Inclusive start character offset into the submitted text. */
383
+ start: number;
384
+ /** Exclusive end character offset into the submitted text. */
385
+ end: number;
386
+ /** Human-readable description of the issue. */
387
+ message: string;
388
+ category: GrammarCategory;
389
+ /** Stable rule identifier, e.g. `retext-spell:colour`. */
390
+ ruleId: string;
391
+ /** Suggested replacements (may be empty). */
392
+ suggestions: string[];
393
+ }
394
+ /** Optional readability summary returned when the readability category is requested. */
395
+ export interface GrammarReadability {
396
+ /** Number of sentences flagged as hard to read. */
397
+ hardToReadSentences: number;
398
+ }
399
+ /** Input to the grammar_check client-side entity. */
400
+ export interface GrammarCheckInput {
401
+ /** The text to check. Capped at 100,000 characters. */
402
+ text: string;
403
+ /** Categories to report. Omitted/empty means all categories. */
404
+ categories?: GrammarCategory[];
405
+ /** Words the user added to their personal dictionary (never flagged as misspelled). */
406
+ customDictionary?: string[];
323
407
  }
324
408
  /**
325
- * Background removal API available via useBackgroundRemoval() hook.
409
+ * Result of a grammar check via the `client_entity_invoke` bridge op
410
+ * targeting the grammar_check entity. The text is checked entirely in the
411
+ * host page (no AI, no network) — it never leaves the user's device.
326
412
  */
327
- export interface BackgroundRemovalApi {
328
- removeBackground: (image: Blob) => Promise<Blob>;
329
- isLoading: boolean;
330
- /** The Blob returned by the most recent successful call, or null. */
331
- result: Blob | null;
332
- error: Error | null;
413
+ export interface GrammarCheckResult {
414
+ issues: GrammarIssue[];
415
+ readability?: GrammarReadability;
416
+ }
417
+ /**
418
+ * A selectable language for the NLLB translator: a human label paired with
419
+ * its FLORES-200 code. See `NLLB_LANGUAGES` for the curated list.
420
+ */
421
+ export interface NllbLanguageOption {
422
+ /** Display label, e.g. `'Spanish'`. */
423
+ label: string;
424
+ /** FLORES-200 code, e.g. `'spa_Latn'`. */
425
+ code: string;
333
426
  }
334
427
  /**
335
428
  * Audio sub-type discriminator. v1 ships music only; future entries
@@ -403,6 +496,23 @@ export interface AudioGenerationApi {
403
496
  */
404
497
  export interface FiasNavigationApi {
405
498
  navigateTo: (path: string) => void;
499
+ /**
500
+ * Navigate the host to ANOTHER arche's page (`/a/<archeId>`).
501
+ *
502
+ * Unlike `navigateTo` (scoped to this arche's own route space), this
503
+ * crosses arches via the host-mediated `open_arche` bridge op. The host
504
+ * validates the id format and performs the navigation itself — the iframe
505
+ * sandbox is never loosened. Requires the `navigation:open_arche`
506
+ * permission in the manifest.
507
+ *
508
+ * @param archeId Target arche id (`arc_<32hex>` or `arche_<slug>`).
509
+ * @param opts.newTab Best-effort open in a new tab (keeps the current arche
510
+ * open). Browsers may block the popup since user activation does not cross
511
+ * the iframe→host boundary; the host falls back to same-tab navigation.
512
+ */
513
+ openArche: (archeId: string, opts?: {
514
+ newTab?: boolean;
515
+ }) => void;
406
516
  currentPath: string;
407
517
  }
408
518
  /**
@@ -719,7 +829,22 @@ export interface ArcheAssetsApi {
719
829
  /**
720
830
  * Message types sent from the plugin iframe to the parent frame.
721
831
  */
722
- export type PluginToHostMessageType = 'ready' | 'resize' | 'toast' | 'get_user' | 'get_theme' | 'storage_read' | 'storage_write' | 'storage_list' | 'storage_delete' | 'entity_invoke' | 'client_entity_invoke' | 'image_generate' | 'entities_list_image' | 'audio_generate' | 'surface_invoke' | 'navigate' | 'data_create_collection' | 'data_list_collections' | 'data_delete_collection' | 'data_put' | 'data_get' | 'data_query' | 'data_delete' | 'store_get_products' | 'store_purchase' | 'store_get_entitlements' | 'store_get_purchase_history' | 'store_restore' | 'store_cancel_subscription' | 'vault_documents_list' | 'vault_documents_read' | 'vault_documents_read_many' | 'vault_documents_download_url' | 'vault_documents_get_urls' | 'vault_documents_search' | 'vault_documents_write' | 'vault_documents_update' | 'vault_documents_delete' | 'vault_documents_attach' | 'vault_documents_detach' | 'vault_documents_upload_init' | 'vault_documents_upload_finalize' | 'arche_assets_list' | 'arche_assets_index' | 'arche_assets_get_url';
832
+ export type PluginToHostMessageType = 'ready' | 'resize' | 'toast' | 'get_user' | 'get_theme' | 'storage_read' | 'storage_write' | 'storage_list' | 'storage_delete' | 'entity_invoke' | 'client_entity_invoke' | 'image_generate' | 'entities_list_image' | 'audio_generate' | 'surface_invoke' | 'navigate' | 'open_arche' | 'data_create_collection' | 'data_list_collections' | 'data_delete_collection' | 'data_put' | 'data_get' | 'data_query' | 'data_delete' | 'data_batch' | 'data_search' | 'workspace_create' | 'workspace_list' | 'workspace_get' | 'workspace_archive' | 'workspace_list_members' | 'workspace_add_member' | 'workspace_update_member' | 'workspace_remove_member' | 'store_get_products' | 'store_purchase' | 'store_get_entitlements' | 'store_get_purchase_history' | 'store_restore' | 'store_cancel_subscription' | 'vault_documents_list' | 'vault_documents_read' | 'vault_documents_read_many' | 'vault_documents_download_url' | 'vault_documents_get_urls' | 'vault_documents_search' | 'vault_documents_write' | 'vault_documents_update' | 'vault_documents_delete' | 'vault_documents_attach' | 'vault_documents_detach' | 'vault_documents_upload_init' | 'vault_documents_upload_finalize' | 'vault_documents_upload' | 'vault_documents_pick' | 'arche_assets_list' | 'arche_assets_index' | 'arche_assets_get_url' | 'preview_state' | 'subscription_unsubscribe';
833
+ /**
834
+ * Why a realtime subscription ended (ADR-012 Phase M4). Closed union so
835
+ * hooks can distinguish terminal endings (`authorization_revoked`,
836
+ * `collection_deleted`) from ones worth resubscribing after conditions
837
+ * change (`limit`, `transport_error`, `lease_expired`).
838
+ */
839
+ export type SubscriptionEndedReason = 'authorization_revoked' | 'lease_expired' | 'collection_deleted' | 'limit' | 'transport_error' | 'unsubscribed';
840
+ /**
841
+ * State reported by useDataSubscription().
842
+ */
843
+ export interface DataSubscriptionState {
844
+ status: 'subscribing' | 'active' | 'ended';
845
+ /** Set once status === 'ended'. */
846
+ endedReason?: SubscriptionEndedReason;
847
+ }
723
848
  /**
724
849
  * Step navigation API available via useStepNavigation() hook.
725
850
  */
@@ -745,7 +870,7 @@ export interface StepNavigationOptions {
745
870
  /**
746
871
  * Message types sent from the parent frame to the plugin iframe.
747
872
  */
748
- export type HostToPluginMessageType = 'init' | 'response' | 'theme_update' | 'navigate_update' | 'step_navigate' | 'stream_token';
873
+ export type HostToPluginMessageType = 'init' | 'response' | 'theme_update' | 'navigate_update' | 'step_navigate' | 'stream_token' | 'preview_state_capture' | 'preview_state_restore' | 'subscription_event' | 'subscription_ended';
749
874
  /**
750
875
  * Base message structure for all bridge communication.
751
876
  */
@@ -762,6 +887,13 @@ export interface BridgeResponse<T = unknown> {
762
887
  messageId: string;
763
888
  payload: T;
764
889
  error?: string;
890
+ /**
891
+ * Machine-readable failure code accompanying `error` (e.g. a server bridge
892
+ * code like `BRIDGE_TOKEN_EXPIRED`, or the host's `BRIDGE_ERROR` fallback).
893
+ * Plain wire field — the SDK constructs a `FiasBridgeError` from
894
+ * `error` + `errorCode` locally; Errors are never structured-cloned.
895
+ */
896
+ errorCode?: string;
765
897
  }
766
898
  /**
767
899
  * Init message sent by the host to the plugin on load.
@@ -771,6 +903,25 @@ export interface BridgeResponse<T = unknown> {
771
903
  * include them still works — the SDK then assumes protocol version 1
772
904
  * (the first published contract).
773
905
  */
906
+ /**
907
+ * Asset URLs for ONE platform-vendored library (see `useFiasVendoredAssets`) —
908
+ * a file-key → absolute-URL map whose keys are defined by that library's
909
+ * registry entry. For `pdfjs-dist`: `mainModule`, `worker`, `cMapUrl`,
910
+ * `standardFontDataUrl`. All URLs share one pinned, immutable CDN version prefix
911
+ * so a library's main module and worker are always the same build.
912
+ */
913
+ export type FiasVendoredLibraryAssets = Record<string, string>;
914
+ /**
915
+ * Self-hosted vendored-library asset URLs, delivered in the init payload to
916
+ * plugins that declare the `sandbox:vendored-libraries` permission. Keyed by
917
+ * import specifier (e.g. `'pdfjs-dist'`). `null`/absent when the host's CDN
918
+ * isn't configured — the plugin then can't load vendored libraries and should
919
+ * degrade gracefully.
920
+ *
921
+ * The shape mirrors `@fias/platform-resources`' registry output, duplicated here
922
+ * so the SDK stays dependency-free (it ships inside plugin iframes).
923
+ */
924
+ export type FiasVendoredAssets = Record<string, FiasVendoredLibraryAssets>;
774
925
  export interface BridgeInitMessage {
775
926
  type: 'init';
776
927
  messageId: string;
@@ -779,6 +930,12 @@ export interface BridgeInitMessage {
779
930
  permissions: PluginPermission[];
780
931
  theme: FiasTheme;
781
932
  currentPath: string;
933
+ /**
934
+ * Self-hosted vendored-library asset URLs (keyed by import specifier) —
935
+ * present only when the plugin declared `sandbox:vendored-libraries` and the
936
+ * host's CDN is configured. Optional for backwards compat with older hosts.
937
+ */
938
+ vendoredAssets?: FiasVendoredAssets | null;
782
939
  /**
783
940
  * Bridge protocol version the HOST speaks. Optional for backwards
784
941
  * compat with hosts pre-dating the versioning work — absence is
@@ -806,6 +963,12 @@ export interface BridgeReadyMessage {
806
963
  payload: {
807
964
  /** Bridge protocol version this SDK speaks. */
808
965
  sdkProtocolVersion: number;
966
+ /**
967
+ * Whether this SDK understands the preview state capture/restore protocol
968
+ * (`preview_state_capture` / `preview_state_restore` / `preview_state`).
969
+ * The host gates capture/restore on this so older SDKs are unaffected.
970
+ */
971
+ supportsPreviewState?: boolean;
809
972
  };
810
973
  }
811
974
  /**
@@ -813,9 +976,36 @@ export interface BridgeReadyMessage {
813
976
  */
814
977
  export interface DataStoreCollection {
815
978
  name: string;
816
- userScope: 'user' | 'shared';
979
+ userScope: 'user' | 'shared' | 'workspace';
980
+ /** True when documents are embedded for semantic search (`data:search`). */
981
+ searchable?: boolean;
982
+ /** Dot-path into `data` that is embedded; present only when `searchable`. */
983
+ searchField?: string | null;
984
+ /** Min workspace role to write / read (workspace-scoped only); null = default. */
985
+ writeMinRole?: WorkspaceRole | null;
986
+ readMinRole?: WorkspaceRole | null;
987
+ /** Who may write (shared-scoped only): see {@link DataStoreWritePolicy}. */
988
+ writePolicy?: DataStoreWritePolicy;
817
989
  createdAt: string;
818
990
  }
991
+ /**
992
+ * Write policy for a `shared`-scope collection. Shared collections are
993
+ * read-by-all; the write policy narrows who may WRITE:
994
+ *
995
+ * - 'any' (default): every user of the arche may write any document.
996
+ * - 'author': creating a NEW key is open to everyone, but overwriting or
997
+ * deleting an existing document requires being its author (the last
998
+ * successful writer) or an arche collaborator. Use for shared catalogs /
999
+ * caches where users publish their own entries.
1000
+ * - 'collaborators': only arche collaborators (owner/publisher) may write.
1001
+ * Use for curated content like a category taxonomy.
1002
+ *
1003
+ * Tighten-only after creation: re-declaring a STRICTER policy on an existing
1004
+ * collection upgrades it when the caller is a collaborator (and is silently
1005
+ * kept as-is for other users, so a shipped `ensure` call stays safe), while
1006
+ * loosening is refused.
1007
+ */
1008
+ export type DataStoreWritePolicy = 'any' | 'author' | 'collaborators';
819
1009
  /**
820
1010
  * A document returned from the data store.
821
1011
  */
@@ -823,6 +1013,15 @@ export interface DataStoreDocument<T = Record<string, unknown>> {
823
1013
  key: string;
824
1014
  data: T;
825
1015
  updatedAt: string;
1016
+ /**
1017
+ * Present on SHARED-scope documents only: whether the document's last writer
1018
+ * is an active arche collaborator (owner/publisher). The trust signal for
1019
+ * shared content — e.g. refuse to feed a document into an AI prompt unless
1020
+ * it was authored by a collaborator. The raw author identity is never
1021
+ * exposed. Requires a platform/SDK version with write-policy support;
1022
+ * absent otherwise.
1023
+ */
1024
+ authoredByCollaborator?: boolean;
826
1025
  }
827
1026
  /**
828
1027
  * Filter condition for querying documents.
@@ -859,6 +1058,28 @@ export interface DataStoreQueryResult<T = Record<string, unknown>> {
859
1058
  /** Cursor for next page, or null if no more results */
860
1059
  nextCursor: string | null;
861
1060
  }
1061
+ /**
1062
+ * Options for semantic search over a searchable collection.
1063
+ */
1064
+ export interface DataStoreSearchOptions {
1065
+ /** Max matches (1-50, default 50). */
1066
+ topK?: number;
1067
+ /** Cosine-similarity floor (0-1, default 0.5). */
1068
+ minSimilarity?: number;
1069
+ /** Optional JSONB facet filters applied alongside the vector match. */
1070
+ filters?: DataStoreQueryFilter[];
1071
+ }
1072
+ /**
1073
+ * A single semantic-search match.
1074
+ */
1075
+ export interface DataStoreSearchMatch<T = Record<string, unknown>> {
1076
+ key: string;
1077
+ data: T;
1078
+ /** Cosine similarity in [0, 1]; higher is closer. */
1079
+ similarity: number;
1080
+ /** Present on shared-scope matches: see {@link DataStoreDocument.authoredByCollaborator}. */
1081
+ authoredByCollaborator?: boolean;
1082
+ }
862
1083
  /**
863
1084
  * Data Store API available via useFiasDataStore() hook.
864
1085
  *
@@ -869,22 +1090,147 @@ export interface DataStoreQueryResult<T = Record<string, unknown>> {
869
1090
  * or 'shared' (all users of the arche share data).
870
1091
  */
871
1092
  export interface FiasDataStoreApi {
872
- /** Create a named collection. Default scope is 'user'. */
1093
+ /**
1094
+ * Create a named collection. Default scope is 'user'. Pass
1095
+ * `searchable: { field }` to make the collection semantically searchable over
1096
+ * a designated text field — documents written to it are embedded
1097
+ * (asynchronously, managed by the platform) and queryable via `search()`.
1098
+ * Searching requires the `data:search` permission.
1099
+ */
873
1100
  createCollection: (name: string, options?: {
874
- userScope?: 'user' | 'shared';
1101
+ userScope?: 'user' | 'shared' | 'workspace';
1102
+ searchable?: {
1103
+ field: string;
1104
+ };
1105
+ /** Workspace-scoped only: raise the min role to write / read this
1106
+ * collection above the default (write ≥ member, read ≥ viewer). */
1107
+ writeMinRole?: WorkspaceRole;
1108
+ readMinRole?: WorkspaceRole;
1109
+ /** Shared-scoped only: who may write. See {@link DataStoreWritePolicy}. */
1110
+ writePolicy?: DataStoreWritePolicy;
875
1111
  }) => Promise<DataStoreCollection>;
876
1112
  /** List all collections for this arche. */
877
1113
  listCollections: () => Promise<DataStoreCollection[]>;
878
1114
  /** Delete a collection and all its documents. */
879
1115
  deleteCollection: (name: string) => Promise<void>;
880
- /** Write (upsert) a document by key. */
881
- put: <T extends Record<string, unknown> = Record<string, unknown>>(collection: string, key: string, data: T) => Promise<void>;
882
- /** Get a document by key. Returns null if not found. */
883
- get: <T extends Record<string, unknown> = Record<string, unknown>>(collection: string, key: string) => Promise<T | null>;
884
- /** Query documents with filters, sorting, and pagination. */
885
- query: <T extends Record<string, unknown> = Record<string, unknown>>(collection: string, options?: DataStoreQueryOptions) => Promise<DataStoreQueryResult<T>>;
886
- /** Delete a document by key. */
887
- delete: (collection: string, key: string) => Promise<void>;
1116
+ /**
1117
+ * Write (upsert) a document by key. For a `workspace`-scoped collection pass
1118
+ * `{ workspaceId }`; the caller must be an active member with write access
1119
+ * (owner/admin/member). See {@link FiasWorkspacesApi}.
1120
+ */
1121
+ put: <T extends Record<string, unknown> = Record<string, unknown>>(collection: string, key: string, data: T, options?: DataStoreScopeOptions) => Promise<void>;
1122
+ /** Get a document by key. Returns null if not found. Pass `{ workspaceId }`
1123
+ * for a workspace-scoped collection. */
1124
+ get: <T extends Record<string, unknown> = Record<string, unknown>>(collection: string, key: string, options?: DataStoreScopeOptions) => Promise<T | null>;
1125
+ /**
1126
+ * Like {@link get}, but returns the full document envelope — key,
1127
+ * `updatedAt`, and (for shared-scope documents) the
1128
+ * {@link DataStoreDocument.authoredByCollaborator} trust signal — instead of
1129
+ * the bare data. Use when the caller needs provenance, e.g. before feeding
1130
+ * shared content into an AI prompt.
1131
+ */
1132
+ getDocument: <T extends Record<string, unknown> = Record<string, unknown>>(collection: string, key: string, options?: DataStoreScopeOptions) => Promise<DataStoreDocument<T> | null>;
1133
+ /** Query documents with filters, sorting, and pagination. For a
1134
+ * `workspace`-scoped collection pass `scope: { workspaceId }`; the caller must
1135
+ * be an active member (any role can read). */
1136
+ query: <T extends Record<string, unknown> = Record<string, unknown>>(collection: string, options?: DataStoreQueryOptions, scope?: DataStoreScopeOptions) => Promise<DataStoreQueryResult<T>>;
1137
+ /**
1138
+ * Semantic search over a `searchable` collection. Charges the caller's
1139
+ * credits for the query embedding. Requires the `data:search` permission. For
1140
+ * a `workspace`-scoped collection pass `scope: { workspaceId }` (any active
1141
+ * member can search).
1142
+ */
1143
+ search: <T extends Record<string, unknown> = Record<string, unknown>>(collection: string, query: string, options?: DataStoreSearchOptions, scope?: DataStoreScopeOptions) => Promise<DataStoreSearchMatch<T>[]>;
1144
+ /** Delete a document by key. Pass `{ workspaceId }` for a workspace-scoped
1145
+ * collection (requires owner/admin/member). */
1146
+ delete: (collection: string, key: string, options?: DataStoreScopeOptions) => Promise<void>;
1147
+ /**
1148
+ * Apply up to 25 put/delete operations in a SINGLE transaction — all-or-
1149
+ * nothing. Use for data-integrity flows (e.g. issuing a ledger entry AND
1150
+ * updating a running total together) where a sequence of separate calls could
1151
+ * leave a half-applied state. A batch may span collections and scopes; any
1152
+ * failure (bad key, role denial, quota) rolls the whole batch back.
1153
+ */
1154
+ batch: (operations: DataStoreBatchOp[]) => Promise<void>;
1155
+ }
1156
+ /** Per-call scope options for workspace-scoped Data Store documents. */
1157
+ export interface DataStoreScopeOptions {
1158
+ /** Target workspace for a `workspace`-scoped collection. */
1159
+ workspaceId?: string;
1160
+ }
1161
+ /**
1162
+ * One write in an atomic batch (see {@link FiasDataStoreApi.batch}). A `put`
1163
+ * upserts a document; a `delete` removes one. `workspaceId` targets a
1164
+ * workspace-scoped collection.
1165
+ */
1166
+ export type DataStoreBatchOp = {
1167
+ op: 'put';
1168
+ collection: string;
1169
+ key: string;
1170
+ data: Record<string, unknown>;
1171
+ workspaceId?: string;
1172
+ } | {
1173
+ op: 'delete';
1174
+ collection: string;
1175
+ key: string;
1176
+ workspaceId?: string;
1177
+ };
1178
+ /** Role a user holds within a workspace, in descending privilege. */
1179
+ export type WorkspaceRole = 'owner' | 'admin' | 'member' | 'viewer';
1180
+ /** A workspace (tenant) the caller belongs to. */
1181
+ export interface DataStoreWorkspace {
1182
+ workspaceId: string;
1183
+ displayName: string;
1184
+ /** The calling user's role in this workspace. */
1185
+ role: WorkspaceRole;
1186
+ createdAt: string;
1187
+ /** Soft-archive timestamp; null while active. */
1188
+ archivedAt: string | null;
1189
+ }
1190
+ /** A member of a workspace. Members are addressed by username — the platform
1191
+ * userId is internal and never exposed to plugins or users. */
1192
+ export interface DataStoreWorkspaceMember {
1193
+ username: string;
1194
+ role: WorkspaceRole;
1195
+ grantedAt: string;
1196
+ /** ISO-8601 expiry, or null for a permanent membership. Owners never expire. */
1197
+ expiresAt: string | null;
1198
+ }
1199
+ /**
1200
+ * Workspace tenancy API available via the `useFiasWorkspaces()` hook.
1201
+ *
1202
+ * Lets a plugin model team/org workspaces with role-gated membership
1203
+ * (owner/admin/member/viewer) over `workspace`-scoped Data Store collections.
1204
+ * The creating user becomes the founding owner. Role rules (enforced server-side):
1205
+ * - owner: manage the workspace + members, read/write docs
1206
+ * - admin: manage members (not owners), read/write docs
1207
+ * - member: read/write docs
1208
+ * - viewer: read docs only
1209
+ * A workspace always keeps at least one owner.
1210
+ *
1211
+ * Requires the `data:workspace` permission in fias-plugin.json. Reading/writing
1212
+ * the workspace's documents additionally uses `useFiasDataStore` (`data:store`)
1213
+ * with the `{ workspaceId }` option.
1214
+ */
1215
+ export interface FiasWorkspacesApi {
1216
+ /** Create a workspace; the caller becomes its owner. */
1217
+ create: (displayName: string) => Promise<DataStoreWorkspace>;
1218
+ /** List the workspaces the caller is an active member of. */
1219
+ list: () => Promise<DataStoreWorkspace[]>;
1220
+ /** Get a single workspace (caller must be a member). */
1221
+ get: (workspaceId: string) => Promise<DataStoreWorkspace>;
1222
+ /** Archive a workspace (owner only). */
1223
+ archive: (workspaceId: string) => Promise<void>;
1224
+ /** List a workspace's members (any member). */
1225
+ listMembers: (workspaceId: string) => Promise<DataStoreWorkspaceMember[]>;
1226
+ /** Add a member by username, with a role (owner/admin; cannot grant above your
1227
+ * own role). Optionally time-bound the membership with an ISO-8601 `expiresAt`
1228
+ * (owners cannot expire). Rejects with `USER_NOT_FOUND` if no such user. */
1229
+ addMember: (workspaceId: string, username: string, role: WorkspaceRole, expiresAt?: string) => Promise<DataStoreWorkspaceMember>;
1230
+ /** Change a member's role by username (owner/admin; keeps the one-owner invariant). */
1231
+ updateMember: (workspaceId: string, username: string, role: WorkspaceRole) => Promise<DataStoreWorkspaceMember>;
1232
+ /** Remove a member by username (owner/admin, or yourself; keeps the one-owner invariant). */
1233
+ removeMember: (workspaceId: string, username: string) => Promise<void>;
888
1234
  }
889
1235
  /**
890
1236
  * IAP product type (mirrors Apple StoreKit).