@fias/arche-sdk 2.26.0 → 2.28.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
@@ -2240,7 +2240,8 @@ function useArcheAssets() {
2240
2240
  return bridge.request("arche_assets_list", {
2241
2241
  cursor: options?.cursor,
2242
2242
  limit: options?.limit,
2243
- tags: options?.tags
2243
+ tags: options?.tags,
2244
+ kinds: options?.kinds
2244
2245
  });
2245
2246
  },
2246
2247
  [bridge]
@@ -2249,7 +2250,8 @@ function useArcheAssets() {
2249
2250
  async (options) => {
2250
2251
  return bridge.request("arche_assets_index", {
2251
2252
  tags: options?.tags,
2252
- groupBy: options?.groupBy
2253
+ groupBy: options?.groupBy,
2254
+ kinds: options?.kinds
2253
2255
  });
2254
2256
  },
2255
2257
  [bridge]
@@ -2262,7 +2264,327 @@ function useArcheAssets() {
2262
2264
  );
2263
2265
  return useMemo2(() => ({ list, index, getUrl }), [list, index, getUrl]);
2264
2266
  }
2267
+ function useArcheAssetBytes() {
2268
+ const bridge = useBridge();
2269
+ const getBytes = useCallback(
2270
+ async (asset) => {
2271
+ let ref;
2272
+ if (typeof asset === "string") {
2273
+ try {
2274
+ ref = await bridge.request("arche_assets_get_url", { assetId: asset });
2275
+ } catch (err) {
2276
+ throw toArcheAssetError(err);
2277
+ }
2278
+ } else {
2279
+ ref = asset;
2280
+ }
2281
+ return enqueueAssetByteRead(bridge, ref);
2282
+ },
2283
+ [bridge]
2284
+ );
2285
+ const getMany = useCallback(
2286
+ async (assets) => {
2287
+ const read = await readAssetBytesBatch(bridge, assets);
2288
+ const out = {};
2289
+ for (const [assetId, result] of read) out[assetId] = result;
2290
+ return out;
2291
+ },
2292
+ [bridge]
2293
+ );
2294
+ return useMemo2(() => ({ getBytes, getMany }), [getBytes, getMany]);
2295
+ }
2296
+ var ARCHE_ASSET_BYTES_ENTITY_ID = "ent_intg_arche_asset_bytes_00000";
2297
+ var ArcheAssetError = class extends Error {
2298
+ constructor(message, code) {
2299
+ super(message);
2300
+ this.code = code;
2301
+ this.name = "ArcheAssetError";
2302
+ }
2303
+ };
2304
+ var ASSET_URL_MIN_REMAINING_SECONDS = 30;
2305
+ var ASSET_BYTES_MAX_URLS_PER_CALL = 100;
2306
+ var ASSET_URL_MAX_REFRESHES_PER_BATCH = 10;
2307
+ async function readSignedUrls(bridge, signedUrls) {
2308
+ let response;
2309
+ try {
2310
+ response = await bridge.request(
2311
+ "client_entity_invoke",
2312
+ { entityId: ARCHE_ASSET_BYTES_ENTITY_ID, input: { verb: "read", signedUrls } },
2313
+ CLIENT_ENTITY_INVOKE_TIMEOUT_MS
2314
+ );
2315
+ } catch (err) {
2316
+ throw toArcheAssetError(err);
2317
+ }
2318
+ if ("error" in response) {
2319
+ throw new ArcheAssetError(response.error.message, response.error.code);
2320
+ }
2321
+ return response.results;
2322
+ }
2323
+ function fileError(result) {
2324
+ return result && "error" in result ? new ArcheAssetError(result.error.message, result.error.code) : new ArcheAssetError("the asset could not be read", "ASSET_UNAVAILABLE");
2325
+ }
2326
+ async function readInBatches(bridge, items, out) {
2327
+ const lapsed = [];
2328
+ let queue = items;
2329
+ while (queue.length > 0) {
2330
+ const overBudget = [];
2331
+ let readCount = 0;
2332
+ for (let at = 0; at < queue.length; at += ASSET_BYTES_MAX_URLS_PER_CALL) {
2333
+ const chunk = queue.slice(at, at + ASSET_BYTES_MAX_URLS_PER_CALL);
2334
+ const results = await readSignedUrls(
2335
+ bridge,
2336
+ chunk.map((item) => item.signedUrl)
2337
+ );
2338
+ chunk.forEach((item, i) => {
2339
+ const result = results[i];
2340
+ if (result && !("error" in result)) {
2341
+ out.set(item.assetId, result);
2342
+ readCount += 1;
2343
+ } else if (result?.error.code === "ASSET_URL_EXPIRED" && !item.refreshed) {
2344
+ lapsed.push(item);
2345
+ } else if (result?.error.code === "ASSET_TOO_LARGE" && chunk.length > 1) {
2346
+ overBudget.push(item);
2347
+ } else {
2348
+ out.set(item.assetId, fileError(result));
2349
+ }
2350
+ });
2351
+ }
2352
+ if (readCount === 0) {
2353
+ for (const item of overBudget) {
2354
+ out.set(
2355
+ item.assetId,
2356
+ new ArcheAssetError("the asset is too large to read", "ASSET_TOO_LARGE")
2357
+ );
2358
+ }
2359
+ break;
2360
+ }
2361
+ queue = overBudget;
2362
+ }
2363
+ return lapsed;
2364
+ }
2365
+ async function readAssetBytesBatch(bridge, refs) {
2366
+ const out = /* @__PURE__ */ new Map();
2367
+ let refreshesLeft = ASSET_URL_MAX_REFRESHES_PER_BATCH;
2368
+ const refresh = async (assetIds) => {
2369
+ const fresh = [];
2370
+ for (const assetId of assetIds) {
2371
+ if (refreshesLeft <= 0) {
2372
+ out.set(
2373
+ assetId,
2374
+ new ArcheAssetError(
2375
+ "the asset URL has expired; list the assets again for fresh URLs",
2376
+ "ASSET_URL_EXPIRED"
2377
+ )
2378
+ );
2379
+ continue;
2380
+ }
2381
+ refreshesLeft -= 1;
2382
+ try {
2383
+ const asset = await bridge.request("arche_assets_get_url", { assetId });
2384
+ fresh.push({ assetId, signedUrl: asset.signedUrl, refreshed: true });
2385
+ } catch (err) {
2386
+ out.set(assetId, toArcheAssetError(err));
2387
+ }
2388
+ }
2389
+ return fresh;
2390
+ };
2391
+ const unique = /* @__PURE__ */ new Map();
2392
+ for (const ref of refs) if (!unique.has(ref.assetId)) unique.set(ref.assetId, ref);
2393
+ const nowSeconds = Date.now() / 1e3;
2394
+ const reusable = [];
2395
+ const stale = [];
2396
+ for (const ref of unique.values()) {
2397
+ if (ref.expiresAt - nowSeconds > ASSET_URL_MIN_REMAINING_SECONDS) {
2398
+ reusable.push({ assetId: ref.assetId, signedUrl: ref.signedUrl, refreshed: false });
2399
+ } else {
2400
+ stale.push(ref.assetId);
2401
+ }
2402
+ }
2403
+ const pending = [...reusable, ...await refresh(stale)];
2404
+ const lapsed = await readInBatches(bridge, pending, out);
2405
+ if (lapsed.length > 0) {
2406
+ await readInBatches(bridge, await refresh(lapsed.map((item) => item.assetId)), out);
2407
+ }
2408
+ return out;
2409
+ }
2410
+ var pendingAssetByteReads = /* @__PURE__ */ new WeakMap();
2411
+ function enqueueAssetByteRead(bridge, ref) {
2412
+ let batch = pendingAssetByteReads.get(bridge);
2413
+ if (!batch) {
2414
+ const created = { refs: [], waiters: [] };
2415
+ pendingAssetByteReads.set(bridge, created);
2416
+ batch = created;
2417
+ void Promise.resolve().then(() => flushAssetByteReads(bridge, created));
2418
+ }
2419
+ batch.refs.push(ref);
2420
+ const queued = batch;
2421
+ return new Promise((resolve, reject) => {
2422
+ queued.waiters.push({ assetId: ref.assetId, resolve, reject });
2423
+ });
2424
+ }
2425
+ async function flushAssetByteReads(bridge, batch) {
2426
+ pendingAssetByteReads.delete(bridge);
2427
+ let results;
2428
+ try {
2429
+ results = await readAssetBytesBatch(bridge, batch.refs);
2430
+ } catch (err) {
2431
+ const failure = toArcheAssetError(err);
2432
+ for (const waiter of batch.waiters) waiter.reject(failure);
2433
+ return;
2434
+ }
2435
+ const handedOut = /* @__PURE__ */ new Set();
2436
+ for (const waiter of batch.waiters) {
2437
+ const result = results.get(waiter.assetId) ?? new ArcheAssetError("the asset could not be read", "ASSET_UNAVAILABLE");
2438
+ if (result instanceof ArcheAssetError) {
2439
+ waiter.reject(result);
2440
+ } else if (handedOut.has(waiter.assetId)) {
2441
+ waiter.resolve({ ...result, bytes: result.bytes.slice(0) });
2442
+ } else {
2443
+ handedOut.add(waiter.assetId);
2444
+ waiter.resolve(result);
2445
+ }
2446
+ }
2447
+ }
2448
+ function toArcheAssetError(err) {
2449
+ if (err instanceof ArcheAssetError) return err;
2450
+ const message = err instanceof Error ? err.message : String(err);
2451
+ const code = err?.code;
2452
+ if (/permission denied/i.test(message)) {
2453
+ return new ArcheAssetError(
2454
+ `${message} \u2014 useArcheAssetBytes needs both "assets:read" and "entities:client_invoke" in fias-plugin.json`,
2455
+ "PERMISSION_DENIED"
2456
+ );
2457
+ }
2458
+ if (code === "RATE_LIMITED" || code === "RATE_LIMIT" || /rate limit/i.test(message)) {
2459
+ return new ArcheAssetError(message, "RATE_LIMIT");
2460
+ }
2461
+ if (/rapid-fire loop|runaway loop/i.test(message)) {
2462
+ return new ArcheAssetError(
2463
+ `${message} Load many assets with useArcheAssetBytes().getMany(entries) \u2014 one call per 100.`,
2464
+ "RATE_LIMIT"
2465
+ );
2466
+ }
2467
+ return new ArcheAssetError(message, "ASSET_UNAVAILABLE");
2468
+ }
2265
2469
  var PLUGIN_CONTENT_ENTITY_ID = "ent_intg_plugin_content_00000000";
2470
+ var PLUGIN_LOCAL_STORE_ENTITY_ID = "ent_intg_plugin_local_store_0000";
2471
+ var FiasLocalStoreError = class extends Error {
2472
+ constructor(message, code) {
2473
+ super(message);
2474
+ this.code = code;
2475
+ this.name = "FiasLocalStoreError";
2476
+ }
2477
+ };
2478
+ function toLocalStoreError(err) {
2479
+ if (err instanceof FiasLocalStoreError) return err;
2480
+ const message = err instanceof Error ? err.message : String(err);
2481
+ const raw = err?.code;
2482
+ const code = raw === "PERMISSION_DENIED" || /permission denied/i.test(message) ? "PERMISSION_DENIED" : raw === "RATE_LIMIT" || raw === "RATE_LIMITED" || /rate limit/i.test(message) ? "RATE_LIMIT" : "LOCAL_STORE_UNAVAILABLE";
2483
+ return new FiasLocalStoreError(message, code);
2484
+ }
2485
+ function useLocalStore() {
2486
+ const bridge = useBridge();
2487
+ const call = useCallback(
2488
+ async (input) => {
2489
+ let response;
2490
+ try {
2491
+ response = await bridge.request(
2492
+ "client_entity_invoke",
2493
+ { entityId: PLUGIN_LOCAL_STORE_ENTITY_ID, input },
2494
+ CLIENT_ENTITY_INVOKE_TIMEOUT_MS
2495
+ );
2496
+ } catch (err) {
2497
+ throw toLocalStoreError(err);
2498
+ }
2499
+ if (response?.error) {
2500
+ throw new FiasLocalStoreError(response.error.message, response.error.code);
2501
+ }
2502
+ return response ?? {};
2503
+ },
2504
+ [bridge]
2505
+ );
2506
+ const get = useCallback(
2507
+ async (key) => (await call({ verb: "get", key })).entry ?? null,
2508
+ [call]
2509
+ );
2510
+ const getText = useCallback(
2511
+ async (key) => {
2512
+ const entry = await get(key);
2513
+ if (!entry) return null;
2514
+ if (typeof entry.value !== "string") {
2515
+ throw new FiasLocalStoreError(`"${key}" does not hold text`, "LOCAL_STORE_WRONG_KIND");
2516
+ }
2517
+ return entry.value;
2518
+ },
2519
+ [get]
2520
+ );
2521
+ const getBytes = useCallback(
2522
+ async (key) => {
2523
+ const entry = await get(key);
2524
+ if (!entry) return null;
2525
+ if (!(entry.value instanceof ArrayBuffer)) {
2526
+ throw new FiasLocalStoreError(`"${key}" does not hold bytes`, "LOCAL_STORE_WRONG_KIND");
2527
+ }
2528
+ return entry.value;
2529
+ },
2530
+ [get]
2531
+ );
2532
+ const getJson = useCallback(
2533
+ async (key) => {
2534
+ const entry = await get(key);
2535
+ if (!entry) return null;
2536
+ if (entry.value instanceof ArrayBuffer) {
2537
+ throw new FiasLocalStoreError(`"${key}" holds bytes, not JSON`, "LOCAL_STORE_WRONG_KIND");
2538
+ }
2539
+ if (typeof entry.value === "string") {
2540
+ try {
2541
+ return JSON.parse(entry.value);
2542
+ } catch {
2543
+ throw new FiasLocalStoreError(
2544
+ `"${key}" holds text that is not JSON`,
2545
+ "LOCAL_STORE_WRONG_KIND"
2546
+ );
2547
+ }
2548
+ }
2549
+ return entry.value;
2550
+ },
2551
+ [get]
2552
+ );
2553
+ const getMany = useCallback(
2554
+ async (keys) => (await call({ verb: "get_many", keys })).entries ?? [],
2555
+ [call]
2556
+ );
2557
+ const put = useCallback(
2558
+ async (key, value) => ({
2559
+ sizeBytes: (await call({ verb: "put", key, value })).sizeBytes ?? 0
2560
+ }),
2561
+ [call]
2562
+ );
2563
+ const del = useCallback(
2564
+ async (key) => {
2565
+ await call({ verb: "delete", key });
2566
+ },
2567
+ [call]
2568
+ );
2569
+ const list = useCallback(
2570
+ async (prefix) => (await call({ verb: "list", ...prefix !== void 0 ? { prefix } : {} })).entries ?? [],
2571
+ [call]
2572
+ );
2573
+ const clear = useCallback(
2574
+ async () => ({
2575
+ deleted: (await call({ verb: "clear" })).deleted ?? 0
2576
+ }),
2577
+ [call]
2578
+ );
2579
+ const estimate = useCallback(async () => {
2580
+ const res = await call({ verb: "estimate" });
2581
+ return { usedBytes: res.usedBytes ?? 0, budgetBytes: res.budgetBytes ?? 0 };
2582
+ }, [call]);
2583
+ return useMemo2(
2584
+ () => ({ get, getMany, getText, getBytes, getJson, put, delete: del, list, clear, estimate }),
2585
+ [get, getMany, getText, getBytes, getJson, put, del, list, clear, estimate]
2586
+ );
2587
+ }
2266
2588
  var FiasContentError = class extends Error {
2267
2589
  constructor(message, code, path) {
2268
2590
  super(message);
@@ -2948,6 +3270,7 @@ var VALID_PLUGIN_PERMISSIONS = [
2948
3270
  "assets:community:publish",
2949
3271
  "assets:community:read",
2950
3272
  "assets:read",
3273
+ "data:agents",
2951
3274
  "data:search",
2952
3275
  "data:store",
2953
3276
  "data:workspace",
@@ -2961,6 +3284,7 @@ var VALID_PLUGIN_PERMISSIONS = [
2961
3284
  "entities:web_search",
2962
3285
  "navigation:open_arche",
2963
3286
  "sandbox:vendored-libraries",
3287
+ "storage:local",
2964
3288
  "storage:sandbox",
2965
3289
  "store:purchase",
2966
3290
  "theme:read",
@@ -2980,7 +3304,8 @@ var PLUGIN_PERMISSION_DESCRIPTIONS = {
2980
3304
  "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.",
2981
3305
  "assets:community:publish": "Share images you made here so other people using this arche can see them, and manage what you have shared.",
2982
3306
  "assets:community:read": "Show you images that other people using this arche have shared. Everything shared is checked before anyone can see it.",
2983
- "assets:read": "Show images from this arche's published asset library.",
3307
+ "assets:read": "Show images and play sounds from this arche's published asset library.",
3308
+ "data:agents": "Let Fias AI, and assistants you connect with an API key and allow here, read this arche's data \u2014 and change it where it says so \u2014 even while it is closed.",
2984
3309
  "data:search": "Search this arche's own data semantically \u2014 costs credits per search.",
2985
3310
  "data:store": "Save structured data in this arche's own private database.",
2986
3311
  "data:workspace": "Create team workspaces and manage their members.",
@@ -2994,6 +3319,7 @@ var PLUGIN_PERMISSION_DESCRIPTIONS = {
2994
3319
  "entities:web_search": "Search the live web on your behalf \u2014 costs credits.",
2995
3320
  "navigation:open_arche": "Open other arches for you (navigation only).",
2996
3321
  "sandbox:vendored-libraries": "Load platform-hosted libraries (like the PDF renderer) from the trusted CDN.",
3322
+ "storage:local": "Keep its working files on this device, so a refresh or crash does not lose your work. Nothing leaves your device; cleared when you sign out or when someone else signs in here.",
2997
3323
  "storage:sandbox": "Save files in this arche's own private storage.",
2998
3324
  "store:purchase": "Offer purchases inside the arche (you approve each purchase).",
2999
3325
  "theme:read": "Match your platform theme.",
@@ -5483,6 +5809,7 @@ function validatePanelCatalog(value) {
5483
5809
  return issues.length === 0 ? { ok: true, issues: [] } : { ok: false, issues };
5484
5810
  }
5485
5811
  export {
5812
+ ARCHE_ASSET_BYTES_ENTITY_ID,
5486
5813
  AUDIO_AUDIO_ISOLATION_SURFACE_KEY,
5487
5814
  AUDIO_FORCED_ALIGNMENT_SURFACE_KEY,
5488
5815
  AUDIO_GEMINI_TRANSCRIBE_SURFACE_KEY,
@@ -5494,6 +5821,7 @@ export {
5494
5821
  AUDIO_TTS_SURFACE_KEY,
5495
5822
  AUDIO_VOICE_CHANGER_SURFACE_KEY,
5496
5823
  AUDIO_VOICE_DESIGN_SURFACE_KEY,
5824
+ ArcheAssetError,
5497
5825
  DARK_THEME,
5498
5826
  ENTITY_INVOCATION_HISTORY_LIMITS,
5499
5827
  ENTITY_INVOCATION_REQUEST_LIMITS,
@@ -5502,6 +5830,7 @@ export {
5502
5830
  FiasBridge,
5503
5831
  FiasBridgeError,
5504
5832
  FiasContentError,
5833
+ FiasLocalStoreError,
5505
5834
  FiasProvider,
5506
5835
  GRAMMAR_CHECK_ENTITY_ID,
5507
5836
  IMAGE_SMART_CONTROL_SURFACE_KEY,
@@ -5535,6 +5864,7 @@ export {
5535
5864
  PANEL_THEME_Z_MAX,
5536
5865
  PANEL_TITLE_MAX_LENGTH,
5537
5866
  PLUGIN_CONTENT_ENTITY_ID,
5867
+ PLUGIN_LOCAL_STORE_ENTITY_ID,
5538
5868
  PLUGIN_PERMISSION_DESCRIPTIONS,
5539
5869
  REASONING_EFFORTS,
5540
5870
  SDK_BRIDGE_PROTOCOL_VERSION,
@@ -5555,6 +5885,7 @@ export {
5555
5885
  invocationPayloadByteLimit,
5556
5886
  isValidPluginPermission,
5557
5887
  resetBridge,
5888
+ useArcheAssetBytes,
5558
5889
  useArcheAssets,
5559
5890
  useArcheHandoff,
5560
5891
  useAudioGeneration,
@@ -5589,6 +5920,7 @@ export {
5589
5920
  useImageEntities,
5590
5921
  useImageGeneration,
5591
5922
  useIntegrationWebSearch,
5923
+ useLocalStore,
5592
5924
  useLyriaMusic,
5593
5925
  usePersistentState,
5594
5926
  useSmartControl,