@arbidocs/sdk 0.3.47 → 0.3.48

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.
@@ -879,7 +879,12 @@ declare function updateDocuments(arbi: ArbiClient, documents: DocUpdateRequest$1
879
879
  title?: string | null | undefined;
880
880
  } | null | undefined;
881
881
  }[]>;
882
- declare function uploadUrl(arbi: ArbiClient, urls: string[], workspaceId: string, shared?: boolean): Promise<{
882
+ /**
883
+ * Kick off a URL-based document ingestion. The active workspace is resolved
884
+ * server-side from the open session — there is no ``workspace_ext_id`` query
885
+ * param on this endpoint.
886
+ */
887
+ declare function uploadUrl(arbi: ArbiClient, urls: string[], shared?: boolean): Promise<{
883
888
  doc_ext_ids?: string[] | undefined;
884
889
  batch_id?: string | null | undefined;
885
890
  skipped?: {
@@ -892,13 +897,15 @@ declare function uploadUrl(arbi: ArbiClient, urls: string[], workspaceId: string
892
897
  */
893
898
  declare function getParsedContent(auth: AuthHeaders, docId: string, stage: string): Promise<Record<string, unknown>>;
894
899
  /**
895
- * Upload a file to a workspace. Uses raw fetch for multipart upload.
900
+ * Upload a file. Uses raw fetch for multipart upload. The active workspace is
901
+ * resolved server-side from the open session.
896
902
  */
897
- declare function uploadFile$1(auth: AuthHeaders, workspaceId: string, fileData: Blob, fileName: string, options?: UploadOptions): Promise<UploadResult>;
903
+ declare function uploadFile$1(auth: AuthHeaders, fileData: Blob, fileName: string, options?: UploadOptions): Promise<UploadResult>;
898
904
  /**
899
- * Upload multiple files in a single FormData request with an optional folder parameter.
905
+ * Upload multiple files in a single FormData request with an optional folder
906
+ * parameter. Workspace is resolved from the session, same as ``uploadFile``.
900
907
  */
901
- declare function uploadFiles(auth: AuthHeaders, workspaceId: string, files: Array<{
908
+ declare function uploadFiles(auth: AuthHeaders, files: Array<{
902
909
  data: Blob;
903
910
  name: string;
904
911
  }>, options?: UploadOptions): Promise<UploadResult>;
@@ -927,6 +934,22 @@ interface UploadDirectOptions {
927
934
  tagExtId?: string;
928
935
  /** Expiry for presigned PUT URLs, in seconds. Defaults to server default (1h). */
929
936
  presignExpiresIn?: number;
937
+ /**
938
+ * Fired as each file's ciphertext is uploaded. In the browser this yields
939
+ * byte-level progress (XMLHttpRequest upload.progress); in Node this fires
940
+ * once per file with `loaded === total` after each PUT completes.
941
+ *
942
+ * - `fileIndex` indexes into the `files` array passed to the helper.
943
+ * - `fileName` is the corresponding `DirectUploadFile.name`.
944
+ * - `loaded` / `total` are bytes of the *ciphertext* (= raw + 40).
945
+ */
946
+ onBytesProgress?: (progress: DirectUploadProgress) => void;
947
+ }
948
+ interface DirectUploadProgress {
949
+ fileIndex: number;
950
+ fileName: string;
951
+ loaded: number;
952
+ total: number;
930
953
  }
931
954
  interface UploadDirectResult {
932
955
  /** Doc ext IDs that were committed and will process through the parse pipeline. */
@@ -939,6 +962,23 @@ interface UploadDirectResult {
939
962
  */
940
963
  skipped: SkippedFile[];
941
964
  }
965
+ /**
966
+ * Structural subset of ``ArbiClient`` that ``uploadDocumentsDirect`` actually
967
+ * uses. The helper only needs the openapi-fetch client, so consumers that don't
968
+ * have a full ``ArbiClient`` (e.g. the React frontend, which wires openapi-fetch
969
+ * through its own middleware) can pass ``{ fetch }`` directly without a cast.
970
+ */
971
+ type DirectUploadClient = Pick<ArbiClient, 'fetch'>;
972
+ /**
973
+ * Minimal extension → MIME mapping to avoid a `mime-types` dep.
974
+ *
975
+ * Browser callers don't usually need this — a File's `.type` is already
976
+ * populated by the browser — but CLI/Node callers construct Blobs from raw
977
+ * bytes and must set the MIME explicitly, otherwise multipart parts land as
978
+ * `application/octet-stream`. Exported for both consumers so the mapping
979
+ * lives in one place.
980
+ */
981
+ declare function mimeFromName(name: string): string | undefined;
942
982
  /**
943
983
  * Upload files via the direct-to-MinIO flow (SecretBox on the client,
944
984
  * presigned PUT to nginx→MinIO, then commit).
@@ -959,9 +999,11 @@ interface UploadDirectResult {
959
999
  * callers that want to upload files from disk should use the wrapper in
960
1000
  * ``documents-node`` which reads ``fs`` into the ``data`` field.
961
1001
  */
962
- declare function uploadDocumentsDirect(arbi: ArbiClient, workspaceKey: Uint8Array, files: DirectUploadFile[], options?: UploadDirectOptions): Promise<UploadDirectResult>;
1002
+ declare function uploadDocumentsDirect(arbi: DirectUploadClient, workspaceKey: Uint8Array, files: DirectUploadFile[], options?: UploadDirectOptions): Promise<UploadDirectResult>;
963
1003
 
1004
+ type documents_DirectUploadClient = DirectUploadClient;
964
1005
  type documents_DirectUploadFile = DirectUploadFile;
1006
+ type documents_DirectUploadProgress = DirectUploadProgress;
965
1007
  type documents_DocumentListFields = DocumentListFields;
966
1008
  type documents_DocumentListOrder = DocumentListOrder;
967
1009
  type documents_ListAllOptions = ListAllOptions;
@@ -981,13 +1023,14 @@ declare const documents_getParsedContent: typeof getParsedContent;
981
1023
  declare const documents_listAll: typeof listAll;
982
1024
  declare const documents_listDocuments: typeof listDocuments;
983
1025
  declare const documents_listPaginated: typeof listPaginated;
1026
+ declare const documents_mimeFromName: typeof mimeFromName;
984
1027
  declare const documents_sanitizeFolderPath: typeof sanitizeFolderPath;
985
1028
  declare const documents_updateDocuments: typeof updateDocuments;
986
1029
  declare const documents_uploadDocumentsDirect: typeof uploadDocumentsDirect;
987
1030
  declare const documents_uploadFiles: typeof uploadFiles;
988
1031
  declare const documents_uploadUrl: typeof uploadUrl;
989
1032
  declare namespace documents {
990
- export { type documents_DirectUploadFile as DirectUploadFile, type documents_DocumentListFields as DocumentListFields, type documents_DocumentListOrder as DocumentListOrder, type documents_ListAllOptions as ListAllOptions, type documents_ListPaginatedOptions as ListPaginatedOptions, documents_MAX_PAGES as MAX_PAGES, documents_SUPPORTED_EXTENSIONS as SUPPORTED_EXTENSIONS, type documents_SkippedFile as SkippedFile, type documents_UploadBatchResult as UploadBatchResult, type documents_UploadDirectOptions as UploadDirectOptions, type documents_UploadDirectResult as UploadDirectResult, type documents_UploadOptions as UploadOptions, type documents_UploadResult as UploadResult, documents_deleteDocuments as deleteDocuments, documents_downloadDocument as downloadDocument, documents_getDocuments as getDocuments, documents_getParsedContent as getParsedContent, documents_listAll as listAll, documents_listDocuments as listDocuments, documents_listPaginated as listPaginated, documents_sanitizeFolderPath as sanitizeFolderPath, documents_updateDocuments as updateDocuments, documents_uploadDocumentsDirect as uploadDocumentsDirect, uploadFile$1 as uploadFile, documents_uploadFiles as uploadFiles, documents_uploadUrl as uploadUrl };
1033
+ export { type documents_DirectUploadClient as DirectUploadClient, type documents_DirectUploadFile as DirectUploadFile, type documents_DirectUploadProgress as DirectUploadProgress, type documents_DocumentListFields as DocumentListFields, type documents_DocumentListOrder as DocumentListOrder, type documents_ListAllOptions as ListAllOptions, type documents_ListPaginatedOptions as ListPaginatedOptions, documents_MAX_PAGES as MAX_PAGES, documents_SUPPORTED_EXTENSIONS as SUPPORTED_EXTENSIONS, type documents_SkippedFile as SkippedFile, type documents_UploadBatchResult as UploadBatchResult, type documents_UploadDirectOptions as UploadDirectOptions, type documents_UploadDirectResult as UploadDirectResult, type documents_UploadOptions as UploadOptions, type documents_UploadResult as UploadResult, documents_deleteDocuments as deleteDocuments, documents_downloadDocument as downloadDocument, documents_getDocuments as getDocuments, documents_getParsedContent as getParsedContent, documents_listAll as listAll, documents_listDocuments as listDocuments, documents_listPaginated as listPaginated, documents_mimeFromName as mimeFromName, documents_sanitizeFolderPath as sanitizeFolderPath, documents_updateDocuments as updateDocuments, documents_uploadDocumentsDirect as uploadDocumentsDirect, uploadFile$1 as uploadFile, documents_uploadFiles as uploadFiles, documents_uploadUrl as uploadUrl };
991
1034
  }
992
1035
 
993
1036
  /**
@@ -1802,7 +1845,7 @@ declare class Arbi {
1802
1845
  title?: string | null | undefined;
1803
1846
  } | null | undefined;
1804
1847
  }[]>;
1805
- uploadUrl: (urls: string[], shared?: boolean, workspaceId?: string) => Promise<{
1848
+ uploadUrl: (urls: string[], shared?: boolean) => Promise<{
1806
1849
  doc_ext_ids?: string[] | undefined;
1807
1850
  batch_id?: string | null | undefined;
1808
1851
  skipped?: {
@@ -1811,7 +1854,6 @@ declare class Arbi {
1811
1854
  }[] | undefined;
1812
1855
  }>;
1813
1856
  uploadFile: (fileData: Blob, fileName: string, options?: {
1814
- workspaceId?: string;
1815
1857
  folder?: string;
1816
1858
  }) => Promise<UploadResult>;
1817
1859
  download: (docId: string) => Promise<Response>;
@@ -2388,6 +2430,7 @@ declare class Arbi {
2388
2430
  show_templates: boolean;
2389
2431
  show_pa_mode: boolean;
2390
2432
  show_agent_sessions: boolean;
2433
+ use_s3_direct_upload: boolean;
2391
2434
  hide_online_status: boolean;
2392
2435
  muted_users: string[];
2393
2436
  premium_model?: string | null | undefined;
@@ -2581,7 +2624,6 @@ declare class Arbi {
2581
2624
  };
2582
2625
  Chunker: {
2583
2626
  MAX_CHUNK_TOKENS: number;
2584
- TOKENIZER_TYPE: "tiktoken" | "huggingface";
2585
2627
  TOKENIZER_NAME: string;
2586
2628
  };
2587
2629
  Embedder: {
@@ -3674,6 +3716,7 @@ declare function getSettings(arbi: ArbiClient): Promise<{
3674
3716
  show_templates: boolean;
3675
3717
  show_pa_mode: boolean;
3676
3718
  show_agent_sessions: boolean;
3719
+ use_s3_direct_upload: boolean;
3677
3720
  hide_online_status: boolean;
3678
3721
  muted_users: string[];
3679
3722
  premium_model?: string | null | undefined;
@@ -3877,7 +3920,6 @@ declare function getConfig(arbi: ArbiClient, configId: string): Promise<{
3877
3920
  };
3878
3921
  Chunker: {
3879
3922
  MAX_CHUNK_TOKENS: number;
3880
- TOKENIZER_TYPE: "tiktoken" | "huggingface";
3881
3923
  TOKENIZER_NAME: string;
3882
3924
  };
3883
3925
  Embedder: {
@@ -879,7 +879,12 @@ declare function updateDocuments(arbi: ArbiClient, documents: DocUpdateRequest$1
879
879
  title?: string | null | undefined;
880
880
  } | null | undefined;
881
881
  }[]>;
882
- declare function uploadUrl(arbi: ArbiClient, urls: string[], workspaceId: string, shared?: boolean): Promise<{
882
+ /**
883
+ * Kick off a URL-based document ingestion. The active workspace is resolved
884
+ * server-side from the open session — there is no ``workspace_ext_id`` query
885
+ * param on this endpoint.
886
+ */
887
+ declare function uploadUrl(arbi: ArbiClient, urls: string[], shared?: boolean): Promise<{
883
888
  doc_ext_ids?: string[] | undefined;
884
889
  batch_id?: string | null | undefined;
885
890
  skipped?: {
@@ -892,13 +897,15 @@ declare function uploadUrl(arbi: ArbiClient, urls: string[], workspaceId: string
892
897
  */
893
898
  declare function getParsedContent(auth: AuthHeaders, docId: string, stage: string): Promise<Record<string, unknown>>;
894
899
  /**
895
- * Upload a file to a workspace. Uses raw fetch for multipart upload.
900
+ * Upload a file. Uses raw fetch for multipart upload. The active workspace is
901
+ * resolved server-side from the open session.
896
902
  */
897
- declare function uploadFile$1(auth: AuthHeaders, workspaceId: string, fileData: Blob, fileName: string, options?: UploadOptions): Promise<UploadResult>;
903
+ declare function uploadFile$1(auth: AuthHeaders, fileData: Blob, fileName: string, options?: UploadOptions): Promise<UploadResult>;
898
904
  /**
899
- * Upload multiple files in a single FormData request with an optional folder parameter.
905
+ * Upload multiple files in a single FormData request with an optional folder
906
+ * parameter. Workspace is resolved from the session, same as ``uploadFile``.
900
907
  */
901
- declare function uploadFiles(auth: AuthHeaders, workspaceId: string, files: Array<{
908
+ declare function uploadFiles(auth: AuthHeaders, files: Array<{
902
909
  data: Blob;
903
910
  name: string;
904
911
  }>, options?: UploadOptions): Promise<UploadResult>;
@@ -927,6 +934,22 @@ interface UploadDirectOptions {
927
934
  tagExtId?: string;
928
935
  /** Expiry for presigned PUT URLs, in seconds. Defaults to server default (1h). */
929
936
  presignExpiresIn?: number;
937
+ /**
938
+ * Fired as each file's ciphertext is uploaded. In the browser this yields
939
+ * byte-level progress (XMLHttpRequest upload.progress); in Node this fires
940
+ * once per file with `loaded === total` after each PUT completes.
941
+ *
942
+ * - `fileIndex` indexes into the `files` array passed to the helper.
943
+ * - `fileName` is the corresponding `DirectUploadFile.name`.
944
+ * - `loaded` / `total` are bytes of the *ciphertext* (= raw + 40).
945
+ */
946
+ onBytesProgress?: (progress: DirectUploadProgress) => void;
947
+ }
948
+ interface DirectUploadProgress {
949
+ fileIndex: number;
950
+ fileName: string;
951
+ loaded: number;
952
+ total: number;
930
953
  }
931
954
  interface UploadDirectResult {
932
955
  /** Doc ext IDs that were committed and will process through the parse pipeline. */
@@ -939,6 +962,23 @@ interface UploadDirectResult {
939
962
  */
940
963
  skipped: SkippedFile[];
941
964
  }
965
+ /**
966
+ * Structural subset of ``ArbiClient`` that ``uploadDocumentsDirect`` actually
967
+ * uses. The helper only needs the openapi-fetch client, so consumers that don't
968
+ * have a full ``ArbiClient`` (e.g. the React frontend, which wires openapi-fetch
969
+ * through its own middleware) can pass ``{ fetch }`` directly without a cast.
970
+ */
971
+ type DirectUploadClient = Pick<ArbiClient, 'fetch'>;
972
+ /**
973
+ * Minimal extension → MIME mapping to avoid a `mime-types` dep.
974
+ *
975
+ * Browser callers don't usually need this — a File's `.type` is already
976
+ * populated by the browser — but CLI/Node callers construct Blobs from raw
977
+ * bytes and must set the MIME explicitly, otherwise multipart parts land as
978
+ * `application/octet-stream`. Exported for both consumers so the mapping
979
+ * lives in one place.
980
+ */
981
+ declare function mimeFromName(name: string): string | undefined;
942
982
  /**
943
983
  * Upload files via the direct-to-MinIO flow (SecretBox on the client,
944
984
  * presigned PUT to nginx→MinIO, then commit).
@@ -959,9 +999,11 @@ interface UploadDirectResult {
959
999
  * callers that want to upload files from disk should use the wrapper in
960
1000
  * ``documents-node`` which reads ``fs`` into the ``data`` field.
961
1001
  */
962
- declare function uploadDocumentsDirect(arbi: ArbiClient, workspaceKey: Uint8Array, files: DirectUploadFile[], options?: UploadDirectOptions): Promise<UploadDirectResult>;
1002
+ declare function uploadDocumentsDirect(arbi: DirectUploadClient, workspaceKey: Uint8Array, files: DirectUploadFile[], options?: UploadDirectOptions): Promise<UploadDirectResult>;
963
1003
 
1004
+ type documents_DirectUploadClient = DirectUploadClient;
964
1005
  type documents_DirectUploadFile = DirectUploadFile;
1006
+ type documents_DirectUploadProgress = DirectUploadProgress;
965
1007
  type documents_DocumentListFields = DocumentListFields;
966
1008
  type documents_DocumentListOrder = DocumentListOrder;
967
1009
  type documents_ListAllOptions = ListAllOptions;
@@ -981,13 +1023,14 @@ declare const documents_getParsedContent: typeof getParsedContent;
981
1023
  declare const documents_listAll: typeof listAll;
982
1024
  declare const documents_listDocuments: typeof listDocuments;
983
1025
  declare const documents_listPaginated: typeof listPaginated;
1026
+ declare const documents_mimeFromName: typeof mimeFromName;
984
1027
  declare const documents_sanitizeFolderPath: typeof sanitizeFolderPath;
985
1028
  declare const documents_updateDocuments: typeof updateDocuments;
986
1029
  declare const documents_uploadDocumentsDirect: typeof uploadDocumentsDirect;
987
1030
  declare const documents_uploadFiles: typeof uploadFiles;
988
1031
  declare const documents_uploadUrl: typeof uploadUrl;
989
1032
  declare namespace documents {
990
- export { type documents_DirectUploadFile as DirectUploadFile, type documents_DocumentListFields as DocumentListFields, type documents_DocumentListOrder as DocumentListOrder, type documents_ListAllOptions as ListAllOptions, type documents_ListPaginatedOptions as ListPaginatedOptions, documents_MAX_PAGES as MAX_PAGES, documents_SUPPORTED_EXTENSIONS as SUPPORTED_EXTENSIONS, type documents_SkippedFile as SkippedFile, type documents_UploadBatchResult as UploadBatchResult, type documents_UploadDirectOptions as UploadDirectOptions, type documents_UploadDirectResult as UploadDirectResult, type documents_UploadOptions as UploadOptions, type documents_UploadResult as UploadResult, documents_deleteDocuments as deleteDocuments, documents_downloadDocument as downloadDocument, documents_getDocuments as getDocuments, documents_getParsedContent as getParsedContent, documents_listAll as listAll, documents_listDocuments as listDocuments, documents_listPaginated as listPaginated, documents_sanitizeFolderPath as sanitizeFolderPath, documents_updateDocuments as updateDocuments, documents_uploadDocumentsDirect as uploadDocumentsDirect, uploadFile$1 as uploadFile, documents_uploadFiles as uploadFiles, documents_uploadUrl as uploadUrl };
1033
+ export { type documents_DirectUploadClient as DirectUploadClient, type documents_DirectUploadFile as DirectUploadFile, type documents_DirectUploadProgress as DirectUploadProgress, type documents_DocumentListFields as DocumentListFields, type documents_DocumentListOrder as DocumentListOrder, type documents_ListAllOptions as ListAllOptions, type documents_ListPaginatedOptions as ListPaginatedOptions, documents_MAX_PAGES as MAX_PAGES, documents_SUPPORTED_EXTENSIONS as SUPPORTED_EXTENSIONS, type documents_SkippedFile as SkippedFile, type documents_UploadBatchResult as UploadBatchResult, type documents_UploadDirectOptions as UploadDirectOptions, type documents_UploadDirectResult as UploadDirectResult, type documents_UploadOptions as UploadOptions, type documents_UploadResult as UploadResult, documents_deleteDocuments as deleteDocuments, documents_downloadDocument as downloadDocument, documents_getDocuments as getDocuments, documents_getParsedContent as getParsedContent, documents_listAll as listAll, documents_listDocuments as listDocuments, documents_listPaginated as listPaginated, documents_mimeFromName as mimeFromName, documents_sanitizeFolderPath as sanitizeFolderPath, documents_updateDocuments as updateDocuments, documents_uploadDocumentsDirect as uploadDocumentsDirect, uploadFile$1 as uploadFile, documents_uploadFiles as uploadFiles, documents_uploadUrl as uploadUrl };
991
1034
  }
992
1035
 
993
1036
  /**
@@ -1802,7 +1845,7 @@ declare class Arbi {
1802
1845
  title?: string | null | undefined;
1803
1846
  } | null | undefined;
1804
1847
  }[]>;
1805
- uploadUrl: (urls: string[], shared?: boolean, workspaceId?: string) => Promise<{
1848
+ uploadUrl: (urls: string[], shared?: boolean) => Promise<{
1806
1849
  doc_ext_ids?: string[] | undefined;
1807
1850
  batch_id?: string | null | undefined;
1808
1851
  skipped?: {
@@ -1811,7 +1854,6 @@ declare class Arbi {
1811
1854
  }[] | undefined;
1812
1855
  }>;
1813
1856
  uploadFile: (fileData: Blob, fileName: string, options?: {
1814
- workspaceId?: string;
1815
1857
  folder?: string;
1816
1858
  }) => Promise<UploadResult>;
1817
1859
  download: (docId: string) => Promise<Response>;
@@ -2388,6 +2430,7 @@ declare class Arbi {
2388
2430
  show_templates: boolean;
2389
2431
  show_pa_mode: boolean;
2390
2432
  show_agent_sessions: boolean;
2433
+ use_s3_direct_upload: boolean;
2391
2434
  hide_online_status: boolean;
2392
2435
  muted_users: string[];
2393
2436
  premium_model?: string | null | undefined;
@@ -2581,7 +2624,6 @@ declare class Arbi {
2581
2624
  };
2582
2625
  Chunker: {
2583
2626
  MAX_CHUNK_TOKENS: number;
2584
- TOKENIZER_TYPE: "tiktoken" | "huggingface";
2585
2627
  TOKENIZER_NAME: string;
2586
2628
  };
2587
2629
  Embedder: {
@@ -3674,6 +3716,7 @@ declare function getSettings(arbi: ArbiClient): Promise<{
3674
3716
  show_templates: boolean;
3675
3717
  show_pa_mode: boolean;
3676
3718
  show_agent_sessions: boolean;
3719
+ use_s3_direct_upload: boolean;
3677
3720
  hide_online_status: boolean;
3678
3721
  muted_users: string[];
3679
3722
  premium_model?: string | null | undefined;
@@ -3877,7 +3920,6 @@ declare function getConfig(arbi: ArbiClient, configId: string): Promise<{
3877
3920
  };
3878
3921
  Chunker: {
3879
3922
  MAX_CHUNK_TOKENS: number;
3880
- TOKENIZER_TYPE: "tiktoken" | "huggingface";
3881
3923
  TOKENIZER_NAME: string;
3882
3924
  };
3883
3925
  Embedder: {
package/dist/browser.cjs CHANGED
@@ -3637,6 +3637,23 @@ async function generateEncryptedWorkspaceKey(arbi, wrappedKey, serverSessionKey,
3637
3637
  const workspaceKey = client.sealedBoxDecrypt(wrappedKey, encryptionKeyPair.secretKey);
3638
3638
  return client.sealKeyForSession(workspaceKey, serverSessionKey);
3639
3639
  }
3640
+ async function getRawWorkspaceKey(arbi, workspaceId, signingPrivateKeyBase64) {
3641
+ const { data: workspaces, error } = await arbi.fetch.GET("/v1/user/workspaces");
3642
+ if (error || !workspaces) {
3643
+ throw new ArbiError("Failed to fetch workspaces");
3644
+ }
3645
+ const ws = workspaces.find((w2) => w2.external_id === workspaceId);
3646
+ if (!ws || !ws.wrapped_key) {
3647
+ throw new ArbiError(`Workspace ${workspaceId} not found or has no encryption key`);
3648
+ }
3649
+ const signingPrivateKey = client.base64ToBytes(signingPrivateKeyBase64);
3650
+ const ed25519PublicKey = signingPrivateKey.slice(32, 64);
3651
+ const encryptionKeyPair = client.deriveEncryptionKeypairFromSigning({
3652
+ publicKey: ed25519PublicKey,
3653
+ secretKey: signingPrivateKey
3654
+ });
3655
+ return client.sealedBoxDecrypt(ws.wrapped_key, encryptionKeyPair.secretKey);
3656
+ }
3640
3657
  async function selectWorkspaceById(arbi, workspaceId, serverSessionKey, signingPrivateKeyBase64) {
3641
3658
  const { data: workspaces, error } = await arbi.fetch.GET("/v1/user/workspaces");
3642
3659
  if (error || !workspaces) {
@@ -4106,6 +4123,7 @@ __export(documents_exports, {
4106
4123
  listAll: () => listAll,
4107
4124
  listDocuments: () => listDocuments,
4108
4125
  listPaginated: () => listPaginated,
4126
+ mimeFromName: () => mimeFromName,
4109
4127
  sanitizeFolderPath: () => sanitizeFolderPath,
4110
4128
  updateDocuments: () => updateDocuments,
4111
4129
  uploadDocumentsDirect: () => uploadDocumentsDirect,
@@ -4255,11 +4273,11 @@ async function updateDocuments(arbi, documents) {
4255
4273
  "Failed to update documents"
4256
4274
  );
4257
4275
  }
4258
- async function uploadUrl(arbi, urls, workspaceId, shared = false) {
4276
+ async function uploadUrl(arbi, urls, shared = false) {
4259
4277
  return requireData(
4260
4278
  await arbi.fetch.POST("/v1/document/upload-url", {
4261
4279
  params: {
4262
- query: { urls, workspace_ext_id: workspaceId, shared }
4280
+ query: { urls, shared }
4263
4281
  }
4264
4282
  }),
4265
4283
  "Failed to upload from URLs"
@@ -4272,29 +4290,31 @@ async function getParsedContent(auth, docId, stage) {
4272
4290
  });
4273
4291
  return res.json();
4274
4292
  }
4275
- async function uploadFile(auth, workspaceId, fileData, fileName, options) {
4293
+ async function uploadFile(auth, fileData, fileName, options) {
4276
4294
  const formData = new FormData();
4277
4295
  formData.append("files", fileData, fileName);
4278
- const params = new URLSearchParams({ workspace_ext_id: workspaceId });
4296
+ const params = new URLSearchParams();
4279
4297
  if (options?.folder) params.set("folder", sanitizeFolderPath(options.folder));
4280
4298
  if (options?.configExtId) params.set("config_ext_id", options.configExtId);
4299
+ const qs = params.toString();
4281
4300
  const res = await authenticatedFetch({
4282
4301
  ...auth,
4283
- path: `/v1/document/upload?${params.toString()}`,
4302
+ path: qs ? `/v1/document/upload?${qs}` : `/v1/document/upload`,
4284
4303
  method: "POST",
4285
4304
  body: formData
4286
4305
  });
4287
4306
  return res.json();
4288
4307
  }
4289
- async function uploadFiles(auth, workspaceId, files, options) {
4308
+ async function uploadFiles(auth, files, options) {
4290
4309
  const formData = new FormData();
4291
4310
  for (const f2 of files) formData.append("files", f2.data, f2.name);
4292
- const params = new URLSearchParams({ workspace_ext_id: workspaceId });
4311
+ const params = new URLSearchParams();
4293
4312
  if (options?.folder) params.set("folder", sanitizeFolderPath(options.folder));
4294
4313
  if (options?.configExtId) params.set("config_ext_id", options.configExtId);
4314
+ const qs = params.toString();
4295
4315
  const res = await authenticatedFetch({
4296
4316
  ...auth,
4297
- path: `/v1/document/upload?${params.toString()}`,
4317
+ path: qs ? `/v1/document/upload?${qs}` : `/v1/document/upload`,
4298
4318
  method: "POST",
4299
4319
  body: formData
4300
4320
  });
@@ -4306,6 +4326,68 @@ async function downloadDocument(auth, docId) {
4306
4326
  path: `/v1/document/${docId}/download`
4307
4327
  });
4308
4328
  }
4329
+ function mimeFromName(name) {
4330
+ const dot = name.lastIndexOf(".");
4331
+ const ext = dot === -1 ? "" : name.slice(dot).toLowerCase();
4332
+ switch (ext) {
4333
+ case ".pdf":
4334
+ return "application/pdf";
4335
+ case ".txt":
4336
+ return "text/plain";
4337
+ case ".md":
4338
+ return "text/markdown";
4339
+ case ".html":
4340
+ case ".htm":
4341
+ return "text/html";
4342
+ case ".doc":
4343
+ return "application/msword";
4344
+ case ".docx":
4345
+ return "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
4346
+ case ".xls":
4347
+ return "application/vnd.ms-excel";
4348
+ case ".xlsx":
4349
+ return "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
4350
+ case ".ppt":
4351
+ return "application/vnd.ms-powerpoint";
4352
+ case ".pptx":
4353
+ return "application/vnd.openxmlformats-officedocument.presentationml.presentation";
4354
+ case ".eml":
4355
+ return "message/rfc822";
4356
+ default:
4357
+ return void 0;
4358
+ }
4359
+ }
4360
+ async function presignedPut(url, body, onProgress) {
4361
+ const XhrGlobal = globalThis.XMLHttpRequest;
4362
+ if (XhrGlobal) {
4363
+ await new Promise((resolve, reject) => {
4364
+ const xhr = new XhrGlobal();
4365
+ xhr.open("PUT", url);
4366
+ if (onProgress) {
4367
+ xhr.upload.addEventListener("progress", (e) => {
4368
+ if (e.lengthComputable) onProgress(e.loaded, e.total);
4369
+ });
4370
+ }
4371
+ xhr.addEventListener("load", () => {
4372
+ if (xhr.status >= 200 && xhr.status < 300) {
4373
+ resolve();
4374
+ } else {
4375
+ const snippet = (xhr.responseText || "").slice(0, 200);
4376
+ reject(new Error(`Presigned PUT failed: ${xhr.status} ${snippet}`));
4377
+ }
4378
+ });
4379
+ xhr.addEventListener("error", () => reject(new Error("Presigned PUT network error")));
4380
+ xhr.addEventListener("abort", () => reject(new Error("Presigned PUT aborted")));
4381
+ xhr.send(body);
4382
+ });
4383
+ return;
4384
+ }
4385
+ const putRes = await fetch(url, { method: "PUT", body });
4386
+ if (!putRes.ok) {
4387
+ const snippet = await putRes.text().catch(() => "");
4388
+ throw new Error(`Presigned PUT failed: ${putRes.status} ${snippet.slice(0, 200)}`);
4389
+ }
4390
+ }
4309
4391
  async function uploadDocumentsDirect(arbi, workspaceKey, files, options) {
4310
4392
  if (files.length === 0) return { doc_ext_ids: [], skipped: [] };
4311
4393
  const SECRETBOX_ENVELOPE_OVERHEAD = 40;
@@ -4338,6 +4420,11 @@ async function uploadDocumentsDirect(arbi, workspaceKey, files, options) {
4338
4420
  }
4339
4421
  const skipped = [];
4340
4422
  const toCommit = [];
4423
+ const indexByName = /* @__PURE__ */ new Map();
4424
+ files.forEach((f2, i2) => {
4425
+ if (!indexByName.has(f2.name)) indexByName.set(f2.name, []);
4426
+ indexByName.get(f2.name).push(i2);
4427
+ });
4341
4428
  for (const item of items) {
4342
4429
  if (item.status !== "uploading" || !item.upload_url || !item.doc_ext_id) {
4343
4430
  skipped.push({
@@ -4347,21 +4434,34 @@ async function uploadDocumentsDirect(arbi, workspaceKey, files, options) {
4347
4434
  continue;
4348
4435
  }
4349
4436
  const queue = bytesByName.get(item.file_name);
4350
- if (!queue || queue.length === 0) {
4437
+ const idxQueue = indexByName.get(item.file_name);
4438
+ if (!queue || queue.length === 0 || !idxQueue || idxQueue.length === 0) {
4351
4439
  throw new Error(`upload-init returned slot for unknown file: ${item.file_name}`);
4352
4440
  }
4353
4441
  const raw = queue.shift();
4442
+ const fileIndex = idxQueue.shift();
4354
4443
  const ciphertext = client.encryptFile(raw, workspaceKey);
4355
- const putRes = await fetch(item.upload_url, {
4356
- method: "PUT",
4357
- body: ciphertext
4358
- });
4359
- if (!putRes.ok) {
4360
- const body = await putRes.text().catch(() => "");
4444
+ const total = ciphertext.length;
4445
+ try {
4446
+ await presignedPut(item.upload_url, ciphertext, (loaded, putTotal) => {
4447
+ options?.onBytesProgress?.({
4448
+ fileIndex,
4449
+ fileName: item.file_name,
4450
+ loaded,
4451
+ total: putTotal
4452
+ });
4453
+ });
4454
+ } catch (err) {
4361
4455
  throw new Error(
4362
- `Presigned PUT for ${item.doc_ext_id} failed: ${putRes.status} ${body.slice(0, 200)}`
4456
+ `Presigned PUT for ${item.doc_ext_id} failed: ${err instanceof Error ? err.message : String(err)}`
4363
4457
  );
4364
4458
  }
4459
+ options?.onBytesProgress?.({
4460
+ fileIndex,
4461
+ fileName: item.file_name,
4462
+ loaded: total,
4463
+ total
4464
+ });
4365
4465
  toCommit.push(item.doc_ext_id);
4366
4466
  }
4367
4467
  if (toCommit.length === 0) {
@@ -5202,19 +5302,19 @@ var Arbi = class {
5202
5302
  get: (externalIds) => getDocuments(this.requireClient(), externalIds),
5203
5303
  delete: (externalIds) => deleteDocuments(this.requireClient(), externalIds),
5204
5304
  update: (documents) => updateDocuments(this.requireClient(), documents),
5205
- uploadUrl: (urls, shared, workspaceId) => uploadUrl(
5206
- this.requireClient(),
5207
- urls,
5208
- workspaceId ?? this.requireWorkspace(),
5209
- shared
5210
- ),
5211
- uploadFile: (fileData, fileName, options) => uploadFile(
5212
- this.getAuthHeaders(),
5213
- options?.workspaceId ?? this.requireWorkspace(),
5214
- fileData,
5215
- fileName,
5216
- options?.folder ? { folder: options.folder } : void 0
5217
- ),
5305
+ uploadUrl: (urls, shared) => {
5306
+ this.requireWorkspace();
5307
+ return uploadUrl(this.requireClient(), urls, shared);
5308
+ },
5309
+ uploadFile: (fileData, fileName, options) => {
5310
+ this.requireWorkspace();
5311
+ return uploadFile(
5312
+ this.getAuthHeaders(),
5313
+ fileData,
5314
+ fileName,
5315
+ options?.folder ? { folder: options.folder } : void 0
5316
+ );
5317
+ },
5218
5318
  download: (docId) => downloadDocument(this.getAuthHeaders(), docId),
5219
5319
  getParsedContent: (docId, stage) => getParsedContent(this.getAuthHeaders(), docId, stage)
5220
5320
  };
@@ -5452,6 +5552,7 @@ exports.formatFileSize = formatFileSize;
5452
5552
  exports.formatUserName = formatUserName;
5453
5553
  exports.formatWorkspaceChoices = formatWorkspaceChoices;
5454
5554
  exports.getErrorMessage = getErrorMessage;
5555
+ exports.getRawWorkspaceKey = getRawWorkspaceKey;
5455
5556
  exports.health = health_exports;
5456
5557
  exports.parseSSEEvents = parseSSEEvents;
5457
5558
  exports.performPasswordLogin = performPasswordLogin;