@arke-institute/sdk 3.6.0 → 3.6.3

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.
@@ -6,7 +6,7 @@
6
6
  *
7
7
  * Source: Arke v1 API
8
8
  * Version: 1.0.0
9
- * Generated: 2026-02-07T17:07:45.355Z
9
+ * Generated: 2026-02-09T15:17:42.566Z
10
10
  */
11
11
  type paths = {
12
12
  "/ops-reference": {
@@ -160,6 +160,84 @@ type paths = {
160
160
  patch?: never;
161
161
  trace?: never;
162
162
  };
163
+ "/auth/whoami": {
164
+ parameters: {
165
+ query?: never;
166
+ header?: never;
167
+ path?: never;
168
+ cookie?: never;
169
+ };
170
+ /**
171
+ * Get current identity
172
+ * @description Returns identity information for the authenticated caller.
173
+ *
174
+ * Accepts any valid credential type:
175
+ * - **JWT**: Returns user PI, email, name, and Supabase user ID
176
+ * - **User API Key (uk_)**: Returns user PI and key metadata
177
+ * - **Agent API Key (ak_)**: Returns agent PI, owner PI, and key metadata
178
+ *
179
+ * Use this endpoint to verify credentials are working or to retrieve the caller's entity PI.
180
+ *
181
+ * ---
182
+ * **Permission:** `auth:whoami`
183
+ * **Auth:** required
184
+ */
185
+ get: {
186
+ parameters: {
187
+ query?: never;
188
+ header?: never;
189
+ path?: never;
190
+ cookie?: never;
191
+ };
192
+ requestBody?: never;
193
+ responses: {
194
+ /** @description Identity information */
195
+ 200: {
196
+ headers: {
197
+ [name: string]: unknown;
198
+ };
199
+ content: {
200
+ "application/json": components["schemas"]["WhoamiResponse"];
201
+ };
202
+ };
203
+ /** @description Unauthorized - Missing or invalid authentication */
204
+ 401: {
205
+ headers: {
206
+ [name: string]: unknown;
207
+ };
208
+ content: {
209
+ /**
210
+ * @example {
211
+ * "error": "Unauthorized: Missing or invalid authentication token"
212
+ * }
213
+ */
214
+ "application/json": components["schemas"]["ErrorResponse"];
215
+ };
216
+ };
217
+ /** @description Internal Server Error */
218
+ 500: {
219
+ headers: {
220
+ [name: string]: unknown;
221
+ };
222
+ content: {
223
+ /**
224
+ * @example {
225
+ * "error": "Internal server error"
226
+ * }
227
+ */
228
+ "application/json": components["schemas"]["ErrorResponse"];
229
+ };
230
+ };
231
+ };
232
+ };
233
+ put?: never;
234
+ post?: never;
235
+ delete?: never;
236
+ options?: never;
237
+ head?: never;
238
+ patch?: never;
239
+ trace?: never;
240
+ };
163
241
  "/alpha/invite": {
164
242
  parameters: {
165
243
  query?: never;
@@ -9177,6 +9255,84 @@ type components = {
9177
9255
  [key: string]: unknown;
9178
9256
  };
9179
9257
  };
9258
+ WhoamiUserResponse: {
9259
+ /**
9260
+ * @description Identity type
9261
+ * @enum {string}
9262
+ */
9263
+ type: "user";
9264
+ /**
9265
+ * @description User entity PI (persistent identifier)
9266
+ * @example 01J1SHMAE10000000000000000
9267
+ */
9268
+ pi: string;
9269
+ /**
9270
+ * @description How this identity was authenticated
9271
+ * @example jwt
9272
+ * @enum {string}
9273
+ */
9274
+ auth_method: "jwt" | "api_key";
9275
+ /**
9276
+ * Format: email
9277
+ * @description User email (JWT auth only)
9278
+ * @example ishmael@pequod.ship
9279
+ */
9280
+ email?: string;
9281
+ /**
9282
+ * @description Display name (JWT auth only)
9283
+ * @example Ishmael
9284
+ */
9285
+ name?: string;
9286
+ /**
9287
+ * Format: uuid
9288
+ * @description Supabase Auth user ID (JWT auth only)
9289
+ */
9290
+ supabase_user_id?: string;
9291
+ /**
9292
+ * @description API key prefix (API key auth only)
9293
+ * @example uk_abc1
9294
+ */
9295
+ key_prefix?: string;
9296
+ /**
9297
+ * Format: date-time
9298
+ * @description API key expiration (API key auth only)
9299
+ */
9300
+ key_expires_at?: string;
9301
+ };
9302
+ WhoamiAgentResponse: {
9303
+ /**
9304
+ * @description Identity type
9305
+ * @enum {string}
9306
+ */
9307
+ type: "agent";
9308
+ /**
9309
+ * @description Agent entity PI (persistent identifier)
9310
+ * @example 01J1AGENTID000000000000000
9311
+ */
9312
+ pi: string;
9313
+ /**
9314
+ * @description How this identity was authenticated
9315
+ * @example api_key
9316
+ * @enum {string}
9317
+ */
9318
+ auth_method: "api_key";
9319
+ /**
9320
+ * @description Entity PI of the agent owner
9321
+ * @example 01J1OWNERID0000000000000000
9322
+ */
9323
+ owner_pi: string;
9324
+ /**
9325
+ * @description API key prefix
9326
+ * @example ak_xyz9
9327
+ */
9328
+ key_prefix: string;
9329
+ /**
9330
+ * Format: date-time
9331
+ * @description API key expiration
9332
+ */
9333
+ key_expires_at: string;
9334
+ };
9335
+ WhoamiResponse: components["schemas"]["WhoamiUserResponse"] | components["schemas"]["WhoamiAgentResponse"];
9180
9336
  AlphaInvite: {
9181
9337
  /**
9182
9338
  * Format: uuid
@@ -6,7 +6,7 @@
6
6
  *
7
7
  * Source: Arke v1 API
8
8
  * Version: 1.0.0
9
- * Generated: 2026-02-07T17:07:45.355Z
9
+ * Generated: 2026-02-09T15:17:42.566Z
10
10
  */
11
11
  type paths = {
12
12
  "/ops-reference": {
@@ -160,6 +160,84 @@ type paths = {
160
160
  patch?: never;
161
161
  trace?: never;
162
162
  };
163
+ "/auth/whoami": {
164
+ parameters: {
165
+ query?: never;
166
+ header?: never;
167
+ path?: never;
168
+ cookie?: never;
169
+ };
170
+ /**
171
+ * Get current identity
172
+ * @description Returns identity information for the authenticated caller.
173
+ *
174
+ * Accepts any valid credential type:
175
+ * - **JWT**: Returns user PI, email, name, and Supabase user ID
176
+ * - **User API Key (uk_)**: Returns user PI and key metadata
177
+ * - **Agent API Key (ak_)**: Returns agent PI, owner PI, and key metadata
178
+ *
179
+ * Use this endpoint to verify credentials are working or to retrieve the caller's entity PI.
180
+ *
181
+ * ---
182
+ * **Permission:** `auth:whoami`
183
+ * **Auth:** required
184
+ */
185
+ get: {
186
+ parameters: {
187
+ query?: never;
188
+ header?: never;
189
+ path?: never;
190
+ cookie?: never;
191
+ };
192
+ requestBody?: never;
193
+ responses: {
194
+ /** @description Identity information */
195
+ 200: {
196
+ headers: {
197
+ [name: string]: unknown;
198
+ };
199
+ content: {
200
+ "application/json": components["schemas"]["WhoamiResponse"];
201
+ };
202
+ };
203
+ /** @description Unauthorized - Missing or invalid authentication */
204
+ 401: {
205
+ headers: {
206
+ [name: string]: unknown;
207
+ };
208
+ content: {
209
+ /**
210
+ * @example {
211
+ * "error": "Unauthorized: Missing or invalid authentication token"
212
+ * }
213
+ */
214
+ "application/json": components["schemas"]["ErrorResponse"];
215
+ };
216
+ };
217
+ /** @description Internal Server Error */
218
+ 500: {
219
+ headers: {
220
+ [name: string]: unknown;
221
+ };
222
+ content: {
223
+ /**
224
+ * @example {
225
+ * "error": "Internal server error"
226
+ * }
227
+ */
228
+ "application/json": components["schemas"]["ErrorResponse"];
229
+ };
230
+ };
231
+ };
232
+ };
233
+ put?: never;
234
+ post?: never;
235
+ delete?: never;
236
+ options?: never;
237
+ head?: never;
238
+ patch?: never;
239
+ trace?: never;
240
+ };
163
241
  "/alpha/invite": {
164
242
  parameters: {
165
243
  query?: never;
@@ -9177,6 +9255,84 @@ type components = {
9177
9255
  [key: string]: unknown;
9178
9256
  };
9179
9257
  };
9258
+ WhoamiUserResponse: {
9259
+ /**
9260
+ * @description Identity type
9261
+ * @enum {string}
9262
+ */
9263
+ type: "user";
9264
+ /**
9265
+ * @description User entity PI (persistent identifier)
9266
+ * @example 01J1SHMAE10000000000000000
9267
+ */
9268
+ pi: string;
9269
+ /**
9270
+ * @description How this identity was authenticated
9271
+ * @example jwt
9272
+ * @enum {string}
9273
+ */
9274
+ auth_method: "jwt" | "api_key";
9275
+ /**
9276
+ * Format: email
9277
+ * @description User email (JWT auth only)
9278
+ * @example ishmael@pequod.ship
9279
+ */
9280
+ email?: string;
9281
+ /**
9282
+ * @description Display name (JWT auth only)
9283
+ * @example Ishmael
9284
+ */
9285
+ name?: string;
9286
+ /**
9287
+ * Format: uuid
9288
+ * @description Supabase Auth user ID (JWT auth only)
9289
+ */
9290
+ supabase_user_id?: string;
9291
+ /**
9292
+ * @description API key prefix (API key auth only)
9293
+ * @example uk_abc1
9294
+ */
9295
+ key_prefix?: string;
9296
+ /**
9297
+ * Format: date-time
9298
+ * @description API key expiration (API key auth only)
9299
+ */
9300
+ key_expires_at?: string;
9301
+ };
9302
+ WhoamiAgentResponse: {
9303
+ /**
9304
+ * @description Identity type
9305
+ * @enum {string}
9306
+ */
9307
+ type: "agent";
9308
+ /**
9309
+ * @description Agent entity PI (persistent identifier)
9310
+ * @example 01J1AGENTID000000000000000
9311
+ */
9312
+ pi: string;
9313
+ /**
9314
+ * @description How this identity was authenticated
9315
+ * @example api_key
9316
+ * @enum {string}
9317
+ */
9318
+ auth_method: "api_key";
9319
+ /**
9320
+ * @description Entity PI of the agent owner
9321
+ * @example 01J1OWNERID0000000000000000
9322
+ */
9323
+ owner_pi: string;
9324
+ /**
9325
+ * @description API key prefix
9326
+ * @example ak_xyz9
9327
+ */
9328
+ key_prefix: string;
9329
+ /**
9330
+ * Format: date-time
9331
+ * @description API key expiration
9332
+ */
9333
+ key_expires_at: string;
9334
+ };
9335
+ WhoamiResponse: components["schemas"]["WhoamiUserResponse"] | components["schemas"]["WhoamiAgentResponse"];
9180
9336
  AlphaInvite: {
9181
9337
  /**
9182
9338
  * Format: uuid
@@ -43,6 +43,7 @@ __export(operations_exports, {
43
43
  isCasConflictError: () => isCasConflictError,
44
44
  scanFileList: () => scanFileList,
45
45
  scanFileSystemEntries: () => scanFileSystemEntries,
46
+ uploadToEntity: () => uploadToEntity,
46
47
  uploadTree: () => uploadTree,
47
48
  verifyCid: () => verifyCid,
48
49
  withCasRetry: () => withCasRetry
@@ -859,6 +860,185 @@ function buildUploadTree(items) {
859
860
  return { files, folders };
860
861
  }
861
862
 
863
+ // src/operations/upload/single.ts
864
+ var MAX_CAS_RETRIES = 3;
865
+ async function uploadToEntity(client, entityId, items, options = {}) {
866
+ if (items.length === 0) {
867
+ throw new Error("At least one upload item is required");
868
+ }
869
+ const { onProgress } = options;
870
+ let progressState = {
871
+ phase: "preparing",
872
+ totalBytes: 0,
873
+ uploadedBytes: 0,
874
+ completedFiles: 0,
875
+ totalFiles: items.length
876
+ };
877
+ const reportProgress = (update) => {
878
+ progressState = { ...progressState, ...update };
879
+ onProgress?.(progressState);
880
+ };
881
+ reportProgress({ phase: "preparing" });
882
+ const prepared = await Promise.all(
883
+ items.map((item) => prepareItem(item))
884
+ );
885
+ const keys = prepared.map((p) => p.key);
886
+ const duplicates = keys.filter((key, i) => keys.indexOf(key) !== i);
887
+ if (duplicates.length > 0) {
888
+ const uniqueDupes = [...new Set(duplicates)];
889
+ throw new Error(
890
+ `Duplicate content keys detected: ${uniqueDupes.map((k) => `"${k}"`).join(", ")}. Each file must have a unique key. Provide explicit keys to resolve.`
891
+ );
892
+ }
893
+ const totalBytes = prepared.reduce((sum, p) => sum + p.size, 0);
894
+ reportProgress({ totalBytes });
895
+ const uploadInfos = await Promise.all(
896
+ prepared.map(async (item) => {
897
+ const { data: presigned, error } = await client.api.POST(
898
+ "/entities/{id}/content/upload-url",
899
+ {
900
+ params: { path: { id: entityId } },
901
+ body: {
902
+ cid: item.cid,
903
+ content_type: item.contentType,
904
+ size: item.size
905
+ }
906
+ }
907
+ );
908
+ if (error || !presigned) {
909
+ throw new Error(
910
+ `Failed to get upload URL for ${item.key}: ${JSON.stringify(error)}`
911
+ );
912
+ }
913
+ return {
914
+ ...item,
915
+ uploadUrl: presigned.upload_url
916
+ };
917
+ })
918
+ );
919
+ reportProgress({ phase: "uploading", uploadedBytes: 0 });
920
+ let uploadedBytes = 0;
921
+ await Promise.all(
922
+ uploadInfos.map(async (item) => {
923
+ const response = await fetch(item.uploadUrl, {
924
+ method: "PUT",
925
+ headers: { "Content-Type": item.contentType },
926
+ body: item.bytes
927
+ });
928
+ if (!response.ok) {
929
+ throw new Error(
930
+ `Upload to R2 failed for ${item.key}: ${response.statusText}`
931
+ );
932
+ }
933
+ uploadedBytes += item.size;
934
+ reportProgress({ uploadedBytes });
935
+ })
936
+ );
937
+ const { data: tipData, error: tipError } = await client.api.GET(
938
+ "/entities/{id}/tip",
939
+ { params: { path: { id: entityId } } }
940
+ );
941
+ if (tipError || !tipData) {
942
+ throw new Error(`Failed to get entity tip: ${JSON.stringify(tipError)}`);
943
+ }
944
+ const prevCid = tipData.cid;
945
+ let currentTip = prevCid;
946
+ reportProgress({ phase: "completing", completedFiles: 0 });
947
+ const contents = [];
948
+ let finalCid = currentTip;
949
+ for (let i = 0; i < uploadInfos.length; i++) {
950
+ const item = uploadInfos[i];
951
+ const result = await completeWithRetry(client, entityId, item, currentTip);
952
+ currentTip = result.cid;
953
+ finalCid = result.cid;
954
+ contents.push({
955
+ key: item.key,
956
+ cid: result.contentCid,
957
+ size: item.size,
958
+ contentType: item.contentType,
959
+ filename: item.filename
960
+ });
961
+ reportProgress({ completedFiles: i + 1 });
962
+ }
963
+ return {
964
+ id: entityId,
965
+ cid: finalCid,
966
+ prevCid,
967
+ contents
968
+ };
969
+ }
970
+ async function prepareItem(item) {
971
+ const { data } = item;
972
+ let bytes;
973
+ if (data instanceof Blob) {
974
+ bytes = await data.arrayBuffer();
975
+ } else if (data instanceof ArrayBuffer) {
976
+ bytes = data;
977
+ } else {
978
+ const buffer = new ArrayBuffer(data.byteLength);
979
+ new Uint8Array(buffer).set(data);
980
+ bytes = buffer;
981
+ }
982
+ const size = bytes.byteLength;
983
+ let filename = item.filename;
984
+ let contentType = item.contentType;
985
+ if (data instanceof File) {
986
+ filename = filename ?? data.name;
987
+ contentType = contentType ?? (data.type || getMimeType(data.name));
988
+ }
989
+ contentType = contentType ?? "application/octet-stream";
990
+ if (contentType === "application/octet-stream" && filename) {
991
+ contentType = getMimeType(filename);
992
+ }
993
+ const cid = await computeCid(new Uint8Array(bytes));
994
+ let key = item.key;
995
+ if (!key && filename) {
996
+ const lastDot = filename.lastIndexOf(".");
997
+ key = lastDot > 0 ? filename.substring(0, lastDot) : filename;
998
+ }
999
+ if (!key) {
1000
+ key = `file_${cid.slice(-8)}`;
1001
+ }
1002
+ return { key, bytes, size, contentType, filename, cid };
1003
+ }
1004
+ async function completeWithRetry(client, entityId, item, expectTip) {
1005
+ let tip = expectTip;
1006
+ for (let attempt = 0; attempt < MAX_CAS_RETRIES; attempt++) {
1007
+ const { data, error, response } = await client.api.POST(
1008
+ "/entities/{id}/content/complete",
1009
+ {
1010
+ params: { path: { id: entityId } },
1011
+ body: {
1012
+ key: item.key,
1013
+ cid: item.cid,
1014
+ size: item.size,
1015
+ content_type: item.contentType,
1016
+ filename: item.filename,
1017
+ expect_tip: tip
1018
+ }
1019
+ }
1020
+ );
1021
+ if (data) {
1022
+ return { cid: data.cid, contentCid: data.content.cid };
1023
+ }
1024
+ if (response?.status === 409) {
1025
+ const { data: freshTip, error: tipError } = await client.api.GET(
1026
+ "/entities/{id}/tip",
1027
+ { params: { path: { id: entityId } } }
1028
+ );
1029
+ if (tipError || !freshTip) {
1030
+ throw new Error(`Failed to refresh tip: ${JSON.stringify(tipError)}`);
1031
+ }
1032
+ tip = freshTip.cid;
1033
+ continue;
1034
+ }
1035
+ throw new Error(
1036
+ `Failed to complete upload for ${item.key}: ${JSON.stringify(error)}`
1037
+ );
1038
+ }
1039
+ throw new Error(`Max CAS retries exceeded for ${item.key}`);
1040
+ }
1041
+
862
1042
  // src/operations/folders.ts
863
1043
  var FolderOperations = class {
864
1044
  constructor(client) {
@@ -1056,6 +1236,7 @@ async function withCasRetry(callbacks, options) {
1056
1236
  isCasConflictError,
1057
1237
  scanFileList,
1058
1238
  scanFileSystemEntries,
1239
+ uploadToEntity,
1059
1240
  uploadTree,
1060
1241
  verifyCid,
1061
1242
  withCasRetry