@fias/arche-sdk 2.19.2 → 2.20.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.
package/dist/index.mjs CHANGED
@@ -1840,17 +1840,6 @@ function useVaultDocuments() {
1840
1840
  },
1841
1841
  [bridge]
1842
1842
  );
1843
- const promoteToUserFiles = useCallback(
1844
- async (documentId) => {
1845
- const res = await bridge.request("vault_documents_update", {
1846
- documentId,
1847
- userVisible: true
1848
- });
1849
- downloadUrlCache.delete(documentId);
1850
- return res;
1851
- },
1852
- [bridge]
1853
- );
1854
1843
  const deleteDocument = useCallback(
1855
1844
  async (documentId) => {
1856
1845
  await bridge.request("vault_documents_delete", { documentId });
@@ -1921,15 +1910,25 @@ function useVaultDocuments() {
1921
1910
  sensitivity: params.sensitivity,
1922
1911
  folderPath: params.folderPath,
1923
1912
  replacesDocumentId: params.replacesDocumentId,
1924
- // Opt-in user-visible save. The host turns this into a confirmation
1925
- // the user sees and the iframe cannot script; the server independently
1926
- // requires `vault:user-documents:write` plus a registered folder for
1927
- // this arche. Omitted (the common case) keeps the arche-private default.
1913
+ // A save into the user's Documents. The host turns this into its Save
1914
+ // dialog, which the iframe cannot see or script, and performs the
1915
+ // write itself from the user's session. Omitted (the common case)
1916
+ // keeps the arche-private default.
1917
+ destination: params.destination,
1928
1918
  userVisible: params.userVisible
1929
1919
  });
1930
1920
  },
1931
1921
  [bridge]
1932
1922
  );
1923
+ const saveCopy = useCallback(
1924
+ async (documentId, options) => {
1925
+ return bridge.request("vault_documents_update", {
1926
+ documentId,
1927
+ saveCopy: { ...options?.suggestedName ? { suggestedName: options.suggestedName } : {} }
1928
+ });
1929
+ },
1930
+ [bridge]
1931
+ );
1933
1932
  return useMemo2(
1934
1933
  () => ({
1935
1934
  list,
@@ -1939,12 +1938,12 @@ function useVaultDocuments() {
1939
1938
  getDownloadUrl,
1940
1939
  write,
1941
1940
  update,
1942
- promoteToUserFiles,
1943
1941
  delete: deleteDocument,
1944
1942
  search,
1945
1943
  attach,
1946
1944
  detach,
1947
1945
  upload,
1946
+ saveCopy,
1948
1947
  uploadInit,
1949
1948
  uploadFinalize
1950
1949
  }),
@@ -1956,12 +1955,12 @@ function useVaultDocuments() {
1956
1955
  getDownloadUrl,
1957
1956
  write,
1958
1957
  update,
1959
- promoteToUserFiles,
1960
1958
  deleteDocument,
1961
1959
  search,
1962
1960
  attach,
1963
1961
  detach,
1964
1962
  upload,
1963
+ saveCopy,
1965
1964
  uploadInit,
1966
1965
  uploadFinalize
1967
1966
  ]
@@ -2043,6 +2042,123 @@ function useArcheAssets() {
2043
2042
  );
2044
2043
  return useMemo2(() => ({ list, index, getUrl }), [list, index, getUrl]);
2045
2044
  }
2045
+ var PLUGIN_CONTENT_ENTITY_ID = "ent_intg_plugin_content_00000000";
2046
+ var FiasContentError = class extends Error {
2047
+ constructor(message, code, path) {
2048
+ super(message);
2049
+ this.code = code;
2050
+ this.path = path;
2051
+ this.name = "FiasContentError";
2052
+ }
2053
+ };
2054
+ function toContentError(err) {
2055
+ if (err instanceof FiasContentError) return err;
2056
+ const message = err instanceof Error ? err.message : String(err);
2057
+ const code = err?.code;
2058
+ if (/permission denied/i.test(message)) return new FiasContentError(message, "PERMISSION_DENIED");
2059
+ if (code === "RATE_LIMITED" || /rate limit/i.test(message)) {
2060
+ return new FiasContentError(message, "RATE_LIMIT");
2061
+ }
2062
+ return new FiasContentError(message, "CONTENT_UNAVAILABLE");
2063
+ }
2064
+ function fileResult(results, path) {
2065
+ const result = results?.[path];
2066
+ if (!result) {
2067
+ throw new FiasContentError(`No result for content/${path}`, "CONTENT_UNAVAILABLE", path);
2068
+ }
2069
+ if ("error" in result) throw new FiasContentError(result.error.message, result.error.code, path);
2070
+ return result;
2071
+ }
2072
+ var contentObjectUrls = /* @__PURE__ */ new Map();
2073
+ function useFiasContent() {
2074
+ const bridge = useBridge();
2075
+ const call = useCallback(
2076
+ async (input) => {
2077
+ let response;
2078
+ try {
2079
+ response = await bridge.request(
2080
+ "client_entity_invoke",
2081
+ { entityId: PLUGIN_CONTENT_ENTITY_ID, input },
2082
+ CLIENT_ENTITY_INVOKE_TIMEOUT_MS
2083
+ );
2084
+ } catch (err) {
2085
+ throw toContentError(err);
2086
+ }
2087
+ if (response?.error) {
2088
+ throw new FiasContentError(response.error.message, response.error.code);
2089
+ }
2090
+ return response ?? {};
2091
+ },
2092
+ [bridge]
2093
+ );
2094
+ const list = useCallback(
2095
+ async (prefix) => (await call({ verb: "list", ...prefix !== void 0 ? { prefix } : {} })).files ?? [],
2096
+ [call]
2097
+ );
2098
+ const getText = useCallback(
2099
+ async (path) => {
2100
+ const { results } = await call({ verb: "read", paths: [path], as: "text" });
2101
+ return fileResult(results, path).text;
2102
+ },
2103
+ [call]
2104
+ );
2105
+ const getJson = useCallback(
2106
+ async (path) => JSON.parse(await getText(path)),
2107
+ [getText]
2108
+ );
2109
+ const readBytes = useCallback(
2110
+ async (path) => {
2111
+ const { results } = await call({ verb: "read", paths: [path], as: "bytes" });
2112
+ return fileResult(results, path);
2113
+ },
2114
+ [call]
2115
+ );
2116
+ const getBytes = useCallback(
2117
+ async (path) => (await readBytes(path)).bytes,
2118
+ [readBytes]
2119
+ );
2120
+ const getMany = useCallback(
2121
+ async (paths, as) => {
2122
+ const { results } = await call({ verb: "read", paths, as });
2123
+ const out = {};
2124
+ for (const path of paths) {
2125
+ try {
2126
+ const result = fileResult(results, path);
2127
+ out[path] = as === "text" ? result.text : result.bytes;
2128
+ } catch (err) {
2129
+ out[path] = toContentError(err);
2130
+ }
2131
+ }
2132
+ return out;
2133
+ },
2134
+ [call]
2135
+ );
2136
+ const getObjectUrl = useCallback(
2137
+ async (path) => {
2138
+ const cached = contentObjectUrls.get(path);
2139
+ if (cached) return cached;
2140
+ const pending = readBytes(path).then(
2141
+ ({ bytes, mimeType }) => URL.createObjectURL(new Blob([bytes], { type: mimeType }))
2142
+ );
2143
+ contentObjectUrls.set(path, pending);
2144
+ pending.catch(() => contentObjectUrls.delete(path));
2145
+ return pending;
2146
+ },
2147
+ [readBytes]
2148
+ );
2149
+ const getUrl = useCallback(
2150
+ async (path) => {
2151
+ const { results } = await call({ verb: "url", paths: [path] });
2152
+ const { url, expiresAt } = fileResult(results, path);
2153
+ return { url, expiresAt };
2154
+ },
2155
+ [call]
2156
+ );
2157
+ return useMemo2(
2158
+ () => ({ list, getText, getJson, getBytes, getMany, getObjectUrl, getUrl }),
2159
+ [list, getText, getJson, getBytes, getMany, getObjectUrl, getUrl]
2160
+ );
2161
+ }
2046
2162
  function useFiasPreviewState(key, getState, onRestore) {
2047
2163
  const bridge = useBridge();
2048
2164
  const getStateRef = useRef(getState);
@@ -2133,7 +2249,8 @@ function useVaultUserDocuments() {
2133
2249
  async (options) => {
2134
2250
  return bridge.request("vault_documents_pick", {
2135
2251
  maxDocuments: options?.maxDocuments,
2136
- access: options?.access
2252
+ access: options?.access,
2253
+ ...options?.accept ? { accept: [...options.accept] } : {}
2137
2254
  });
2138
2255
  },
2139
2256
  [bridge]
@@ -2536,6 +2653,7 @@ var VALID_PLUGIN_PERMISSIONS = [
2536
2653
  "store:purchase",
2537
2654
  "theme:read",
2538
2655
  "user:profile:read",
2656
+ "vault:arche-saves:write",
2539
2657
  "vault:documents:read",
2540
2658
  "vault:documents:write",
2541
2659
  "vault:user-documents:edit",
@@ -2546,12 +2664,12 @@ function isValidPluginPermission(perm) {
2546
2664
  return VALID_PLUGIN_PERMISSIONS.includes(perm);
2547
2665
  }
2548
2666
  var PLUGIN_PERMISSION_DESCRIPTIONS = {
2549
- "ai:actions": "Let Fias AI operate this app for you \u2014 only actions you could do yourself in its interface, and risky ones ask you first.",
2550
- "assets:community:publish": "Share images you made here so other people using this app can see them, and manage what you have shared.",
2551
- "assets:community:read": "Show you images that other people using this app have shared. Everything shared is checked before anyone can see it.",
2552
- "assets:read": "Show images from this app's published asset library.",
2553
- "data:search": "Search this app's own data semantically \u2014 costs credits per search.",
2554
- "data:store": "Save structured data in this app's own private database.",
2667
+ "ai:actions": "Let Fias AI operate this arche for you \u2014 only actions you could do yourself in its interface, and risky ones ask you first.",
2668
+ "assets:community:publish": "Share images you made here so other people using this arche can see them, and manage what you have shared.",
2669
+ "assets:community:read": "Show you images that other people using this arche have shared. Everything shared is checked before anyone can see it.",
2670
+ "assets:read": "Show images from this arche's published asset library.",
2671
+ "data:search": "Search this arche's own data semantically \u2014 costs credits per search.",
2672
+ "data:store": "Save structured data in this arche's own private database.",
2555
2673
  "data:workspace": "Create team workspaces and manage their members.",
2556
2674
  "entities:audio_generate": "Generate audio with platform AI \u2014 costs credits.",
2557
2675
  "entities:client_invoke": "Use free on-device tools (grammar check, translation) in your browser.",
@@ -2561,15 +2679,16 @@ var PLUGIN_PERMISSION_DESCRIPTIONS = {
2561
2679
  "entities:web_search": "Search the live web on your behalf \u2014 costs credits.",
2562
2680
  "navigation:open_arche": "Open other arches for you (navigation only).",
2563
2681
  "sandbox:vendored-libraries": "Load platform-hosted libraries (like the PDF renderer) from the trusted CDN.",
2564
- "storage:sandbox": "Save files in this app's own private storage.",
2565
- "store:purchase": "Offer in-app purchases (you approve each purchase).",
2682
+ "storage:sandbox": "Save files in this arche's own private storage.",
2683
+ "store:purchase": "Offer purchases inside the arche (you approve each purchase).",
2566
2684
  "theme:read": "Match your platform theme.",
2567
2685
  "user:profile:read": "See your display name and avatar.",
2568
- "vault:documents:read": "Read documents this app itself created in your Vault.",
2569
- "vault:documents:write": "Create and manage its own documents in your Vault.",
2570
- "vault:user-documents:edit": "Save changes to files of yours that you let it edit \u2014 you choose each file, earlier versions are kept, and you can remove access any time in Vault \u2192 App Access.",
2571
- "vault:user-documents:read": "Read documents YOU choose to share with it from your Vault \u2014 you pick each document, and you can remove access any time in Vault \u2192 App Access.",
2572
- "vault:user-documents:write": "Save its work to your Fias files, where you can find and reuse it. You confirm each save."
2686
+ "vault:arche-saves:write": "Saves files to your Arche Saves automatically.",
2687
+ "vault:documents:read": "Read files this arche itself created, in its own folders of your Vault.",
2688
+ "vault:documents:write": "Create and manage its own files, in its own folder of your Vault.",
2689
+ "vault:user-documents:edit": "Save changes to files of yours that you let it edit \u2014 you choose each file, earlier versions are kept unless you turned version history off, and you can remove access any time in Vault \u2192 Arche Access.",
2690
+ "vault:user-documents:read": "Read documents YOU choose to share with it from your Vault \u2014 you pick each document, and you can remove access any time in Vault \u2192 Arche Access.",
2691
+ "vault:user-documents:write": "Save its work to your Documents \u2014 you choose the folder and the name each time."
2573
2692
  };
2574
2693
 
2575
2694
  // src/fias.ts
@@ -5056,6 +5175,7 @@ export {
5056
5175
  FONT_PAIRINGS,
5057
5176
  FiasBridge,
5058
5177
  FiasBridgeError,
5178
+ FiasContentError,
5059
5179
  FiasProvider,
5060
5180
  GRAMMAR_CHECK_ENTITY_ID,
5061
5181
  IMAGE_SMART_CONTROL_SURFACE_KEY,
@@ -5088,6 +5208,7 @@ export {
5088
5208
  PANEL_THEME_LENGTH_MAX_INTEGER_DIGITS,
5089
5209
  PANEL_THEME_Z_MAX,
5090
5210
  PANEL_TITLE_MAX_LENGTH,
5211
+ PLUGIN_CONTENT_ENTITY_ID,
5091
5212
  PLUGIN_PERMISSION_DESCRIPTIONS,
5092
5213
  SDK_BRIDGE_PROTOCOL_VERSION,
5093
5214
  SDK_REQUIRES_HOST_PROTOCOL_VERSION,
@@ -5118,6 +5239,7 @@ export {
5118
5239
  useElevenLabsVoiceDesign,
5119
5240
  useEntityInvocation,
5120
5241
  useFiasAIActions,
5242
+ useFiasContent,
5121
5243
  useFiasDataStore,
5122
5244
  useFiasFonts,
5123
5245
  useFiasNavigation,
package/dist/types.d.ts CHANGED
@@ -678,6 +678,21 @@ export interface FiasNavigationApi {
678
678
  path?: string;
679
679
  payload?: ArcheHandoffPayloadInput;
680
680
  }) => void;
681
+ /**
682
+ * The host's current path, expressed in THIS plugin's own route space — the
683
+ * same space `navigateTo` accepts. A plugin mounted at
684
+ * `/a/<arche>/my-books` reads `/my-books`, and its home page reads `/`.
685
+ * Parse it with your own router; it never carries the `/a/<arche>` prefix.
686
+ *
687
+ * Tracks the host: it updates after your own `navigateTo`, and when the
688
+ * user moves the host themselves with browser back/forward. A router driven
689
+ * off this value stays in step with the address bar.
690
+ *
691
+ * `''` before the host's `init` message lands (the bridge handshake is
692
+ * async, so the first render usually happens first). Treat the empty string
693
+ * as "not known yet" rather than as the home page — that distinction is what
694
+ * lets a direct entry such as a share link survive the pre-init race.
695
+ */
681
696
  currentPath: string;
682
697
  }
683
698
  /**
@@ -846,20 +861,6 @@ export interface VaultDocumentSaveContentResult {
846
861
  export interface VaultUserDocumentSaveContentResult extends VaultDocumentSaveContentResult {
847
862
  revision: string;
848
863
  }
849
- /** Result of `useVaultDocuments().promoteToUserFiles`. */
850
- export interface VaultDocumentPromoteResult {
851
- documentId: string;
852
- visibility: 'user-vault';
853
- /**
854
- * Whether the user let your app KEEP EDITING the file (a checkbox on the
855
- * host's confirmation, offered only when your manifest declares
856
- * `vault:user-documents:edit`). `true`: keep saving it with
857
- * `useVaultUserDocuments().saveContent`. `false` or absent: it is read-only
858
- * to you now — open it read-only and ask with `requestEditAccess` if the
859
- * user starts editing.
860
- */
861
- editAccess?: boolean;
862
- }
863
864
  export interface VaultDocumentSearchOptions {
864
865
  /** Number of results to return. 1..50, default 10. */
865
866
  topK?: number;
@@ -949,28 +950,49 @@ export interface VaultDocumentUploadParams {
949
950
  /** Optional predecessor for replace-mode uploads. */
950
951
  replacesDocumentId?: string;
951
952
  /**
952
- * Save this as a document the USER owns and can see — it appears in their
953
- * Fias files under your arche's folder, other arches can pick it, and it
954
- * outlives your app. Without this the document is arche-private: yours to
953
+ * Where the file goes. Omitted: your arche's own private space — yours to
955
954
  * read and write, invisible everywhere else.
956
955
  *
956
+ * `'documents'` — into the USER's Documents, through the host **Save
957
+ * dialog**: the user picks the folder, can change the name, settles a name
958
+ * clash (keep both, or replace a file of the same type), and decides what
959
+ * your arche keeps afterwards. `name` is the name you SUGGEST. The result
960
+ * tells you the document id, the final `name` and your `access` — never the
961
+ * folder.
962
+ *
957
963
  * Use it for the artifact the user made and asked you to keep (an edited
958
964
  * image, an exported document). Do NOT use it for your app's own state —
959
965
  * caches, session snapshots, working files — which belong in the default
960
966
  * private space.
961
967
  *
962
- * Requires the `vault:user-documents:write` permission, and the HOST asks
963
- * the user to confirm each save by name. If they decline, this rejects with
964
- * `SAVE_DECLINED`; treat that as a normal outcome, not an error to retry.
965
- * Cannot be combined with `folderPath` (the destination is your arche's
966
- * registered folder), and is unavailable in preview and in the dev harness.
968
+ * Requires `vault:user-documents:write`. If the user cancels, this rejects
969
+ * with `SAVE_DECLINED`; treat that as a normal outcome, not an error to
970
+ * retry. Cannot be combined with `folderPath`, `replacesDocumentId`, `tags`
971
+ * or `sensitivity` (the user decides those — `INVALID_PARAMS`). Unavailable
972
+ * in preview and in the dev harness.
967
973
  *
968
- * `upload` only — the lower-level `uploadInit` cannot do this. The host has
969
- * to run the confirmation, and it can only do that when it is orchestrating
970
- * the whole upload.
974
+ * `upload` only — the lower-level `uploadInit` cannot do this: the host has
975
+ * to show the dialog, and it can only do that when it orchestrates the
976
+ * whole upload.
977
+ *
978
+ * `'arche-saves'` — AUTOMATICALLY into the user's `Arche Saves/<your
979
+ * label>/`, with no dialog. Only for an arche a Fias admin has designated
980
+ * (which issues its label) AND that declares `vault:arche-saves:write`;
981
+ * otherwise it rejects with `ARCHE_NOT_DESIGNATED` or `PERMISSION_DENIED`.
982
+ * The file is user-visible, and your arche keeps reaching it through
983
+ * `useVaultDocuments()` while it stays in Arche Saves. Cannot be combined
984
+ * with `folderPath` or `userVisible`. Use it for outputs the user expects to
985
+ * find without being asked each time; otherwise prefer `'documents'`.
971
986
  */
987
+ destination?: 'documents' | 'arche-saves';
988
+ /** Alias for `destination: 'documents'` (the original spelling). */
972
989
  userVisible?: boolean;
973
990
  }
991
+ /** Options for {@link VaultDocumentsApi.saveCopy}. */
992
+ export interface VaultDocumentSaveCopyOptions {
993
+ /** The name to suggest in the Save dialog. Default: the document's name. */
994
+ suggestedName?: string;
995
+ }
974
996
  export interface VaultDocumentUploadInitResult {
975
997
  documentId: string;
976
998
  /** Presigned PUT URL — the plugin must PUT the bytes to this URL. */
@@ -987,10 +1009,25 @@ export interface VaultDocumentUploadResult {
987
1009
  * extraction worker indexes the document for search. */
988
1010
  status: string;
989
1011
  /**
990
- * Only on `upload({ userVisible: true })`: whether the user let your app
991
- * keep editing the file it just saved into their files. See
992
- * `VaultDocumentPromoteResult.editAccess`.
1012
+ * Only on a save into the user's Documents (`destination: 'documents'`,
1013
+ * `saveCopy`): the name the user kept — it may differ from the one you
1014
+ * suggested ("Report (2).pdf" after "keep both").
1015
+ */
1016
+ name?: string;
1017
+ /**
1018
+ * Only on a save into the user's Documents: what your arche can do with the
1019
+ * file afterwards.
1020
+ * - `'read'` — open it again, through `useVaultUserDocuments()` (declare
1021
+ * `vault:user-documents:read`).
1022
+ * - `'write'` — the user ticked "keep editing": keep saving it with
1023
+ * `useVaultUserDocuments().saveContent` (needs `vault:user-documents:edit`).
1024
+ * - `'none'` — nothing: your arche cannot hold access to it (no `:read`
1025
+ * permission, or the file is proprietary).
1026
+ * The user can change it at any time in Arche Access. The file is theirs:
1027
+ * `useVaultDocuments()` does not list it.
993
1028
  */
1029
+ access?: 'none' | 'read' | 'write';
1030
+ /** Published alias: `access === 'write'`. */
994
1031
  editAccess?: boolean;
995
1032
  }
996
1033
  export interface VaultDocumentReferenceResult {
@@ -1093,38 +1130,6 @@ export interface VaultDocumentsApi {
1093
1130
  * results until re-extraction exists.
1094
1131
  */
1095
1132
  saveContent: (params: VaultDocumentSaveContentParams) => Promise<VaultDocumentSaveContentResult>;
1096
- /**
1097
- * Move a document THIS ARCHE created out of its private space and into the
1098
- * user's own Fias files — the SAME document, not a copy: same `documentId`,
1099
- * no second upload, nothing double-counted against storage. Use it to hand
1100
- * over a finished working file instead of `upload({ userVisible: true })`,
1101
- * which would mint a duplicate.
1102
- *
1103
- * The user decides. The host shows them its own confirmation naming the
1104
- * file and where it will go; this resolves once they agree, and rejects
1105
- * with `SAVE_DECLINED` if they don't (or if the host cannot ask — the dev
1106
- * harness and the builder preview can't). Nothing the plugin sends can skip
1107
- * that step. The file lands in your app's folder under My Fias; you cannot
1108
- * choose another.
1109
- *
1110
- * Requires `vault:user-documents:write` in your manifest (it escalates to
1111
- * human review) and a registered folder for your arche — the same two
1112
- * things `upload({ userVisible: true })` needs.
1113
- *
1114
- * ONE-WAY, and it changes what you can do: once the file is the user's,
1115
- * THIS hook's `saveContent`, `update` and `delete` reject — it is theirs
1116
- * now. To keep saving it, declare `vault:user-documents:edit`: the
1117
- * confirmation then offers the user "let this app keep editing", the result
1118
- * carries `editAccess`, and you save through
1119
- * `useVaultUserDocuments().saveContent` instead. Without that, promote when
1120
- * the user is DONE. There is no plugin-side demote.
1121
- *
1122
- * After a `SAVE_DECLINED`, re-`list()` before assuming nothing moved. The
1123
- * host performs the move itself, so in the rare case its page is torn down
1124
- * mid-move (the user navigates away) you are told "declined" for a promote
1125
- * that completed. The document's `visibility` is the truth.
1126
- */
1127
- promoteToUserFiles: (documentId: string) => Promise<VaultDocumentPromoteResult>;
1128
1133
  /**
1129
1134
  * Get a fresh presigned download URL for a documentId. The result is
1130
1135
  * cached client-side and refreshed automatically before expiry.
@@ -1168,11 +1173,23 @@ export interface VaultDocumentsApi {
1168
1173
  * `'uploaded'` → `'available'`).
1169
1174
  */
1170
1175
  upload: (bytes: ArrayBuffer | Uint8Array, params: VaultDocumentUploadParams) => Promise<VaultDocumentUploadResult>;
1176
+ /**
1177
+ * Hand the user a COPY of one of your own documents: the host Save dialog
1178
+ * opens with its content, the user chooses where it goes in their
1179
+ * Documents, and your working file is left exactly as it was (delete it
1180
+ * afterwards if you no longer need it). Same outcome and result as
1181
+ * `upload(bytes, { destination: 'documents' })`, without re-sending the
1182
+ * bytes.
1183
+ *
1184
+ * Requires `vault:documents:read` (the host reads your file) and
1185
+ * `vault:user-documents:write`. Cancelling rejects with `SAVE_DECLINED`.
1186
+ */
1187
+ saveCopy: (documentId: string, options?: VaultDocumentSaveCopyOptions) => Promise<VaultDocumentUploadResult>;
1171
1188
  /**
1172
1189
  * Lower-level — start an upload, returning a presigned PUT URL.
1173
1190
  * Prefer `upload` unless you need to drive the PUT yourself.
1174
1191
  */
1175
- uploadInit: (params: Omit<VaultDocumentUploadParams, 'userVisible'> & {
1192
+ uploadInit: (params: Omit<VaultDocumentUploadParams, 'userVisible' | 'destination'> & {
1176
1193
  sizeBytes: number;
1177
1194
  checksumSha256: string;
1178
1195
  }) => Promise<VaultDocumentUploadInitResult>;
@@ -1275,6 +1292,51 @@ export interface ArcheAssetsApi {
1275
1292
  /** Refresh the signed URL for a single asset. */
1276
1293
  getUrl: (assetId: string) => Promise<ArcheAsset>;
1277
1294
  }
1295
+ /**
1296
+ * Why a content read failed. The first seven come from the host's content
1297
+ * reader; `PERMISSION_DENIED` (the manifest lacks `entities:client_invoke`)
1298
+ * and `RATE_LIMIT` come from the bridge.
1299
+ */
1300
+ export type FiasContentErrorCode = 'CONTENT_NOT_FOUND' | 'CONTENT_NOT_TEXT' | 'CONTENT_TOO_LARGE' | 'CONTENT_UNAVAILABLE' | 'CONTENT_THROTTLED' | 'CONTENT_UNAVAILABLE_IN_PREVIEW' | 'INVALID_INPUT' | 'PERMISSION_DENIED' | 'RATE_LIMIT';
1301
+ /** One file of the published content pack. `path` is relative to `content/`. */
1302
+ export interface FiasContentFile {
1303
+ path: string;
1304
+ sizeBytes: number;
1305
+ mimeType: string;
1306
+ }
1307
+ /** A signed, arche-scoped URL for streaming media. Request a new one after `expiresAt`. */
1308
+ export interface FiasContentUrl {
1309
+ url: string;
1310
+ expiresAt: string;
1311
+ }
1312
+ export interface FiasContentApi {
1313
+ /** Files in the pack, optionally under a path prefix (e.g. `'lessons/'`). */
1314
+ list(prefix?: string): Promise<FiasContentFile[]>;
1315
+ /** A text file (`.md`, `.txt`, `.json`) as a string. */
1316
+ getText(path: string): Promise<string>;
1317
+ /** A `.json` file, parsed. */
1318
+ getJson<T = unknown>(path: string): Promise<T>;
1319
+ /** Any file as bytes. */
1320
+ getBytes(path: string): Promise<ArrayBuffer>;
1321
+ /**
1322
+ * Up to 100 files in one call (≤ 25 MB together). Each value is the file's
1323
+ * content or the `FiasContentError` for that path — one missing file does
1324
+ * not fail the rest.
1325
+ */
1326
+ getMany(paths: string[], as: 'text'): Promise<Record<string, string | Error>>;
1327
+ getMany(paths: string[], as: 'bytes'): Promise<Record<string, ArrayBuffer | Error>>;
1328
+ /**
1329
+ * A `blob:` URL for `<img>`, `<audio>`, `@font-face` — built in the plugin
1330
+ * from host-cached bytes, so repeat views cost the contributor nothing. The
1331
+ * recommended way to show content images.
1332
+ */
1333
+ getObjectUrl(path: string): Promise<string>;
1334
+ /**
1335
+ * A signed CDN URL, for long media that must stream or seek. Bypasses the
1336
+ * host cache; prefer `getObjectUrl` for anything else.
1337
+ */
1338
+ getUrl(path: string): Promise<FiasContentUrl>;
1339
+ }
1278
1340
  /** Where an asset sits in the moderation lifecycle, from the author's view. */
1279
1341
  export type CommunityAssetStatus =
1280
1342
  /** Awaiting a verdict. Nobody else can see it yet. */
@@ -1551,6 +1613,7 @@ export interface BridgeInitMessage {
1551
1613
  archId: string;
1552
1614
  permissions: PluginPermission[];
1553
1615
  theme: FiasTheme;
1616
+ /** Plugin-relative path — see `FiasNavigationApi.currentPath`. */
1554
1617
  currentPath: string;
1555
1618
  /**
1556
1619
  * Self-hosted vendored-library asset URLs (keyed by import specifier) —