@agentunion/fastaun 0.4.13 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (182) hide show
  1. package/CHANGELOG.md +547 -393
  2. package/_packed_docs/CHANGELOG-validators.md +144 -0
  3. package/_packed_docs/CHANGELOG.md +547 -393
  4. package/_packed_docs/INDEX.md +159 -84
  5. package/_packed_docs/KITE_DOCS_GUIDE.md +48 -31
  6. package/_packed_docs/agent.md/SCHEMA.md +2 -0
  7. package/_packed_docs/agent.md/examples/codeagent-claudecode.md +2 -0
  8. package/_packed_docs/agent.md/examples/human-developer.md +2 -0
  9. package/_packed_docs/agent.md/examples/openclaw-lobster.md +2 -0
  10. package/_packed_docs/agent.md/examples/signed-openclaw-lobster.md +2 -0
  11. package/_packed_docs/agent.md//350/277/234/347/250/213agent.md/347/274/223/345/255/230/344/270/216etag/351/200/217/344/274/240/346/226/271/346/241/210.md +2 -0
  12. package/_packed_docs/cli/AUN-CLI/350/256/276/350/256/241/346/226/207/346/241/243.md +266 -686
  13. package/_packed_docs/cli/CLI/346/211/213/345/206/214.md +331 -0
  14. package/_packed_docs/design/2026-05-22-aun-rpc-trace-enhancement.md +2 -0
  15. package/_packed_docs/design/AUNClient/346/213/206/345/210/206/351/207/215/346/236/204/346/211/247/350/241/214/346/226/271/346/241/210.md +2 -0
  16. package/_packed_docs/design/E2EE_V2/347/256/200/345/214/226/344/270/2721DH/345/212/240Per-AID_Wrap/346/226/271/346/241/210.md +2 -0
  17. package/_packed_docs/design//350/267/250/350/257/255/350/250/200/345/256/271/345/231/250E2E/346/265/213/350/257/225/346/226/271/346/241/210.md +2 -0
  18. package/_packed_docs/protocol/00-/346/200/273/350/247/210/344/270/216/345/210/206/345/261/202.md +2 -0
  19. package/_packed_docs/protocol/00A-/350/256/276/350/256/241/345/216/237/345/210/231-/344/270/272Agent/350/200/214/347/224/237.md +2 -0
  20. package/_packed_docs/protocol/01-/350/272/253/344/273/275/344/270/216/345/207/255/350/257/201/345/215/217/350/256/256-auth.md +2 -0
  21. package/_packed_docs/protocol/02-/350/257/201/344/271/246/344/270/216/344/277/241/344/273/273/344/275/223/347/263/273.md +2 -0
  22. package/_packed_docs/protocol/03-Gateway-/350/277/236/346/216/245/346/250/241/345/274/217.md +2 -0
  23. package/_packed_docs/protocol/04-Peer-/345/255/220/345/215/217/350/256/256.md +2 -0
  24. package/_packed_docs/protocol/05-Relay-/345/255/220/345/215/217/350/256/256.md +2 -0
  25. package/_packed_docs/protocol/07-/351/224/231/350/257/257/347/240/201/344/270/216/347/212/266/346/200/201/346/234/272.md +2 -0
  26. package/_packed_docs/protocol/08-AUN-E2EE-Group.md +296 -900
  27. package/_packed_docs/protocol/08-AUN-E2EE.md +2 -0
  28. package/_packed_docs/protocol/09-/345/256/211/345/205/250/350/200/203/350/231/221.md +2 -0
  29. package/_packed_docs/protocol/10-Group-/345/255/220/345/215/217/350/256/256.md +66 -173
  30. package/_packed_docs/protocol/11-Storage-/345/255/220/345/215/217/350/256/256.md +55 -0
  31. package/_packed_docs/protocol/12-Stream-/345/255/220/345/215/217/350/256/256.md +2 -0
  32. package/_packed_docs/protocol/13-Agent/350/241/214/344/270/272/350/247/204/350/214/203.md +2 -0
  33. package/_packed_docs/protocol/14-/344/272/244/344/272/222/346/234/272/345/210/266-/345/223/215/345/272/224/346/250/241/345/274/217/344/270/216/350/207/252/344/270/273/346/250/241/345/274/217.md +2 -0
  34. package/_packed_docs/protocol/15-/347/246/273/347/272/277/346/216/250/351/200/201/351/200/232/347/237/245/345/215/217/350/256/256.md +2 -0
  35. package/_packed_docs/protocol/16-/347/263/273/347/273/237/347/233/256/345/275/225/344/277/235/346/212/244/346/226/271/346/241/210.md +177 -0
  36. package/_packed_docs/protocol/README.md +4 -1
  37. package/_packed_docs/protocol/agent.md/SCHEMA.md +2 -0
  38. package/_packed_docs/protocol/agent.md/examples/codeagent-claudecode.md +2 -0
  39. package/_packed_docs/protocol/agent.md/examples/human-developer.md +2 -0
  40. package/_packed_docs/protocol/agent.md/examples/openclaw-lobster.md +2 -0
  41. package/_packed_docs/protocol/aun-docs-guide.md +2 -0
  42. package/_packed_docs/protocol/index.md +10 -3
  43. package/_packed_docs/protocol//350/215/211/346/241/210-agent.md/347/255/276/345/220/215/345/215/217/350/256/256.md +2 -0
  44. package/_packed_docs/protocol//350/215/211/346/241/210-/346/213/222/347/273/235/344/277/241/345/217/267/345/215/217/350/256/256.md +2 -0
  45. package/_packed_docs/protocol//351/231/204/345/275/225A-/346/234/257/350/257/255/350/241/250.md +2 -0
  46. package/_packed_docs/protocol//351/231/204/345/275/225B-/346/211/251/345/261/225/346/200/247/346/214/207/345/215/227.md +2 -0
  47. package/_packed_docs/protocol//351/231/204/345/275/225C-/347/247/201/351/222/245/347/256/241/347/220/206/344/270/216/350/272/253/344/273/275/346/201/242/345/244/215.md +2 -0
  48. package/_packed_docs/protocol//351/231/204/345/275/225D-Root_CA_/346/262/273/347/220/206/346/234/272/345/210/266.md +2 -0
  49. package/_packed_docs/protocol//351/231/204/345/275/225E-Root_CA_/345/207/206/345/205/245/346/265/201/347/250/213.md +2 -0
  50. package/_packed_docs/protocol//351/231/204/345/275/225F-Issuer_CA_/347/224/263/350/257/267/346/265/201/347/250/213.md +2 -0
  51. package/_packed_docs/protocol//351/231/204/345/275/225G-AID_/345/255/244/345/204/277/351/242/204/351/230/262/344/270/216/346/225/221/346/217/264/346/234/272/345/210/266.md +2 -0
  52. package/_packed_docs/protocol//351/231/204/345/275/225H-Identity/346/234/215/345/212/241/345/256/236/347/216/260/346/214/207/345/215/227.md +2 -0
  53. package/_packed_docs/protocol//351/231/204/345/275/225I-/350/267/250/345/237/237/346/266/210/346/201/257/350/267/257/347/224/261/345/256/236/347/216/260/346/214/207/345/215/227.md +2 -0
  54. package/_packed_docs/protocol//351/231/204/345/275/225J-/345/256/242/346/210/267/347/253/257/346/216/245/345/205/245/347/244/272/344/276/213.md +2 -0
  55. package/_packed_docs/protocol//351/231/204/345/275/225K-Agent_Web/345/217/221/347/216/260/345/215/217/350/256/256.md +2 -0
  56. package/_packed_docs/protocol//351/231/204/345/275/225L-E2EE/345/256/236/347/216/260/346/214/207/345/215/227.md +2 -0
  57. package/_packed_docs/protocol//351/231/204/345/275/225M-JWT/350/256/244/350/257/201/345/256/236/347/216/260/346/214/207/345/215/227.md +2 -0
  58. package/_packed_docs/protocol//351/231/204/345/275/225N-/345/210/206/345/270/203/345/274/217Trace/345/215/217/350/256/256.md +2 -0
  59. package/_packed_docs/sdk/01-/345/277/253/351/200/237/345/274/200/345/247/213.md +2 -0
  60. package/_packed_docs/sdk/02-WebSocket/345/215/217/350/256/256.md +2 -0
  61. package/_packed_docs/sdk/03-/346/240/270/345/277/203/346/246/202/345/277/265.md +2 -0
  62. package/_packed_docs/sdk/04-/350/277/236/346/216/245/344/270/216/350/256/244/350/257/201.md +2 -0
  63. package/_packed_docs/sdk/05-E2EE/345/212/240/345/257/206/351/200/232/344/277/241.md +6 -252
  64. package/_packed_docs/sdk/06-API/346/211/213/345/206/214.md +219 -177
  65. package/_packed_docs/sdk/07-/351/224/231/350/257/257/345/244/204/347/220/206.md +4 -1
  66. package/_packed_docs/sdk/08-/346/234/200/344/275/263/345/256/236/350/267/265.md +2 -0
  67. package/_packed_docs/sdk/09-collab-rpc-manual.md +581 -0
  68. package/_packed_docs/sdk/09-custody-api-manual.md +2 -0
  69. package/_packed_docs/sdk/09-group-rpc-manual.md +301 -634
  70. package/_packed_docs/sdk/09-message-rpc-manual.md +2 -0
  71. package/_packed_docs/sdk/09-meta-rpc-manual.md +2 -0
  72. package/_packed_docs/sdk/09-payload-reference.md +2 -0
  73. package/_packed_docs/sdk/09-proxy-rpc-manual.md +2 -0
  74. package/_packed_docs/sdk/09-storage-rpc-manual.md +984 -274
  75. package/_packed_docs/sdk/09-stream-rpc-manual.md +2 -0
  76. package/_packed_docs/sdk/AUN_DOCS_GUIDE.md +36 -23
  77. package/_packed_docs/sdk/E2EE_V2/346/266/210/346/201/257/351/200/232/344/277/241/346/227/266/345/272/217/345/233/276.md +2 -0
  78. package/_packed_docs/sdk/INDEX.md +47 -30
  79. package/_packed_docs/sdk/Notify/351/200/232/347/237/245/346/226/271/346/241/210.md +2 -0
  80. package/_packed_docs/sdk/README.md +17 -15
  81. package/dist/aid-store.d.ts +25 -0
  82. package/dist/aid-store.js +80 -0
  83. package/dist/aid-store.js.map +1 -1
  84. package/dist/client/delivery.d.ts +11 -0
  85. package/dist/client/delivery.js +208 -25
  86. package/dist/client/delivery.js.map +1 -1
  87. package/dist/client/group-state.js +33 -11
  88. package/dist/client/group-state.js.map +1 -1
  89. package/dist/client/rpc-pipeline.d.ts +1 -0
  90. package/dist/client/rpc-pipeline.js +177 -65
  91. package/dist/client/rpc-pipeline.js.map +1 -1
  92. package/dist/client/v2-e2ee.d.ts +6 -1
  93. package/dist/client/v2-e2ee.js +199 -130
  94. package/dist/client/v2-e2ee.js.map +1 -1
  95. package/dist/client.d.ts +37 -1
  96. package/dist/client.js +491 -44
  97. package/dist/client.js.map +1 -1
  98. package/dist/collab/client.d.ts +46 -0
  99. package/dist/collab/client.js +136 -0
  100. package/dist/collab/client.js.map +1 -0
  101. package/dist/collab/errors.d.ts +15 -0
  102. package/dist/collab/errors.js +60 -0
  103. package/dist/collab/errors.js.map +1 -0
  104. package/dist/collab/index.d.ts +3 -0
  105. package/dist/collab/index.js +4 -0
  106. package/dist/collab/index.js.map +1 -0
  107. package/dist/collab/types.d.ts +110 -0
  108. package/dist/collab/types.js +2 -0
  109. package/dist/collab/types.js.map +1 -0
  110. package/dist/crypto.d.ts +2 -0
  111. package/dist/crypto.js +6 -0
  112. package/dist/crypto.js.map +1 -1
  113. package/dist/errors.d.ts +0 -12
  114. package/dist/errors.js +9 -25
  115. package/dist/errors.js.map +1 -1
  116. package/dist/facades.d.ts +94 -0
  117. package/dist/facades.js +255 -0
  118. package/dist/facades.js.map +1 -0
  119. package/dist/group-fs.d.ts +122 -0
  120. package/dist/group-fs.js +467 -0
  121. package/dist/group-fs.js.map +1 -0
  122. package/dist/group-id.d.ts +9 -12
  123. package/dist/group-id.js +41 -63
  124. package/dist/group-id.js.map +1 -1
  125. package/dist/group-resources.d.ts +31 -0
  126. package/dist/group-resources.js +84 -0
  127. package/dist/group-resources.js.map +1 -0
  128. package/dist/index.d.ts +9 -3
  129. package/dist/index.js +11 -1
  130. package/dist/index.js.map +1 -1
  131. package/dist/keystore/aid-db.d.ts +1 -0
  132. package/dist/keystore/aid-db.js +43 -43
  133. package/dist/keystore/aid-db.js.map +1 -1
  134. package/dist/keystore/local-identity-store.d.ts +16 -0
  135. package/dist/keystore/local-identity-store.js +190 -18
  136. package/dist/keystore/local-identity-store.js.map +1 -1
  137. package/dist/keystore/local-token-store.d.ts +0 -13
  138. package/dist/keystore/local-token-store.js +0 -105
  139. package/dist/keystore/local-token-store.js.map +1 -1
  140. package/dist/logger.d.ts +2 -0
  141. package/dist/logger.js +4 -0
  142. package/dist/logger.js.map +1 -1
  143. package/dist/register-flow.d.ts +1 -0
  144. package/dist/register-flow.js +3 -0
  145. package/dist/register-flow.js.map +1 -1
  146. package/dist/service-proxy.d.ts +1 -0
  147. package/dist/service-proxy.js +17 -4
  148. package/dist/service-proxy.js.map +1 -1
  149. package/dist/storage/errors.d.ts +27 -0
  150. package/dist/storage/errors.js +65 -0
  151. package/dist/storage/errors.js.map +1 -0
  152. package/dist/storage/index.d.ts +1 -0
  153. package/dist/storage/index.js +2 -0
  154. package/dist/storage/index.js.map +1 -0
  155. package/dist/storage/lowlevel.d.ts +321 -0
  156. package/dist/storage/lowlevel.js +475 -0
  157. package/dist/storage/lowlevel.js.map +1 -0
  158. package/dist/storage/types.d.ts +57 -0
  159. package/dist/storage/types.js +116 -0
  160. package/dist/storage/types.js.map +1 -0
  161. package/dist/storage/vfs.d.ts +166 -0
  162. package/dist/storage/vfs.js +524 -0
  163. package/dist/storage/vfs.js.map +1 -0
  164. package/dist/tools/cross-sdk-agent.js +708 -1
  165. package/dist/tools/cross-sdk-agent.js.map +1 -1
  166. package/dist/transport.d.ts +5 -0
  167. package/dist/transport.js +124 -21
  168. package/dist/transport.js.map +1 -1
  169. package/dist/types.d.ts +38 -0
  170. package/dist/v2/session/session.d.ts +2 -0
  171. package/dist/v2/session/session.js +53 -23
  172. package/dist/v2/session/session.js.map +1 -1
  173. package/dist/v2/state/commitment.d.ts +1 -1
  174. package/dist/v2/state/commitment.js +4 -2
  175. package/dist/v2/state/commitment.js.map +1 -1
  176. package/dist/validators.d.ts +32 -0
  177. package/dist/validators.js +128 -0
  178. package/dist/validators.js.map +1 -0
  179. package/dist/version.d.ts +1 -1
  180. package/dist/version.js +1 -1
  181. package/dist/version.js.map +1 -1
  182. package/package.json +1 -1
@@ -1,5 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import * as http from 'node:http';
3
+ import * as https from 'node:https';
3
4
  import * as crypto from 'node:crypto';
4
5
  import * as fs from 'node:fs';
5
6
  import { URL } from 'node:url';
@@ -53,6 +54,22 @@ function textOf(value) {
53
54
  function jsonObjectOf(value) {
54
55
  return value && typeof value === 'object' && !Array.isArray(value) ? value : null;
55
56
  }
57
+ function withoutKeys(source, keys) {
58
+ const next = { ...source };
59
+ for (const key of keys)
60
+ delete next[key];
61
+ return next;
62
+ }
63
+ function accessTokenFromClient(client) {
64
+ const internals = client;
65
+ const direct = textOf(internals.accessToken ?? internals.access_token).trim();
66
+ if (direct)
67
+ return direct;
68
+ const identityToken = textOf(internals._identity?.access_token).trim();
69
+ if (identityToken)
70
+ return identityToken;
71
+ return textOf(internals._sessionParams?.access_token).trim();
72
+ }
56
73
  function envelopeMetadata(data) {
57
74
  const e2ee = jsonObjectOf(data.e2ee);
58
75
  const protectedHeaders = jsonObjectOf(data.protected_headers) ?? jsonObjectOf(e2ee?.protected_headers);
@@ -295,6 +312,10 @@ class CrossSdkTsAgent {
295
312
  await this.groupCreate(req, res);
296
313
  return;
297
314
  }
315
+ if (req.method === 'POST' && url.pathname === '/group/call') {
316
+ await this.groupCall(req, res);
317
+ return;
318
+ }
298
319
  if (req.method === 'GET' && url.pathname === '/group/ready') {
299
320
  await this.groupReady(url, res);
300
321
  return;
@@ -311,6 +332,18 @@ class CrossSdkTsAgent {
311
332
  await this.groupAck(req, res);
312
333
  return;
313
334
  }
335
+ if (req.method === 'POST' && url.pathname === '/group/fs/call') {
336
+ await this.groupFsCall(req, res);
337
+ return;
338
+ }
339
+ if (req.method === 'POST' && url.pathname === '/collab/call') {
340
+ await this.collabCall(req, res);
341
+ return;
342
+ }
343
+ if (req.method === 'POST' && url.pathname === '/storage/call') {
344
+ await this.storageCall(req, res);
345
+ return;
346
+ }
314
347
  if (req.method === 'GET' && url.pathname === '/inbox') {
315
348
  const traceId = textOf(url.searchParams.get('trace_id') ?? '');
316
349
  const fromAid = textOf(url.searchParams.get('from') ?? '');
@@ -470,12 +503,18 @@ class CrossSdkTsAgent {
470
503
  name,
471
504
  visibility: textOf(body.visibility || 'private'),
472
505
  };
506
+ const groupName = textOf(body.group_name ?? body.groupName ?? '').trim();
507
+ if (groupName)
508
+ params.group_name = groupName;
473
509
  const joinMode = textOf(body.join_mode || '').trim();
474
510
  if (joinMode)
475
511
  params.join_mode = joinMode;
476
512
  try {
477
- const createResult = await this.client.call('group.create', params);
513
+ const createResult = groupName
514
+ ? await this.client.createGroup(params)
515
+ : await this.client.call('group.create', params);
478
516
  const groupId = this.extractGroupId(createResult);
517
+ const groupAid = this.extractGroupAid(createResult);
479
518
  if (!groupId)
480
519
  throw new Error(`group.create did not return group_id: ${JSON.stringify(jsonSafe(createResult))}`);
481
520
  const addResults = [];
@@ -493,6 +532,7 @@ class CrossSdkTsAgent {
493
532
  ok: true,
494
533
  trace_id: traceId,
495
534
  group_id: groupId,
535
+ group_aid: groupAid,
496
536
  create_result: jsonSafe(createResult),
497
537
  add_results: addResults,
498
538
  };
@@ -510,6 +550,605 @@ class CrossSdkTsAgent {
510
550
  sendJson(res, 500, error);
511
551
  }
512
552
  }
553
+ async groupCall(req, res) {
554
+ const body = await readJson(req);
555
+ const traceId = textOf(body.trace_id || crypto.randomUUID().replace(/-/g, ''));
556
+ let method = textOf(body.method).trim();
557
+ const action = textOf(body.action).trim();
558
+ if (!method && action)
559
+ method = action.startsWith('group.') ? action : `group.${action}`;
560
+ const params = jsonObjectOf(body.params) ?? {};
561
+ if (!method) {
562
+ sendJson(res, 400, { ok: false, trace_id: traceId, error_code: 'bad_request', error_message: 'method is required' });
563
+ return;
564
+ }
565
+ try {
566
+ const result = await this.client.call(method, params);
567
+ const response = { ok: true, trace_id: traceId, method, result: jsonSafe(result) };
568
+ this.recordTrace(traceId, { stage: 'group_call', method, result: response });
569
+ sendJson(res, 200, response);
570
+ }
571
+ catch (err) {
572
+ const error = {
573
+ ok: false,
574
+ trace_id: traceId,
575
+ method,
576
+ error_code: err instanceof Error ? err.name : 'Error',
577
+ error_message: err instanceof Error ? err.message : String(err),
578
+ };
579
+ this.recordTrace(traceId, { stage: 'group_call_error', method, error });
580
+ sendJson(res, 500, error);
581
+ }
582
+ }
583
+ async groupFsCall(req, res) {
584
+ const body = await readJson(req);
585
+ const traceId = textOf(body.trace_id || crypto.randomUUID().replace(/-/g, ''));
586
+ const action = textOf(body.action).trim();
587
+ const params = jsonObjectOf(body.params) ?? {};
588
+ const asGroupAid = textOf(body.as_group_aid || body.asGroupAid || params.as_group_aid || params.asGroupAid).trim();
589
+ delete params.as_group_aid;
590
+ delete params.asGroupAid;
591
+ try {
592
+ const result = await this.callGroupFsAction(action, params, asGroupAid);
593
+ const response = { ok: true, trace_id: traceId, action, result: jsonSafe(result) };
594
+ this.recordTrace(traceId, { stage: 'group_fs_call', action, as_group_aid: asGroupAid, result: response });
595
+ sendJson(res, 200, response);
596
+ }
597
+ catch (err) {
598
+ const error = {
599
+ ok: false,
600
+ trace_id: traceId,
601
+ action,
602
+ error_code: err instanceof Error ? err.name : 'Error',
603
+ error_message: err instanceof Error ? err.message : String(err),
604
+ };
605
+ this.recordTrace(traceId, { stage: 'group_fs_call_error', action, as_group_aid: asGroupAid, error });
606
+ sendJson(res, 500, error);
607
+ }
608
+ }
609
+ async collabCall(req, res) {
610
+ const body = await readJson(req);
611
+ const traceId = textOf(body.trace_id || crypto.randomUUID().replace(/-/g, ''));
612
+ const action = textOf(body.action).trim();
613
+ const params = jsonObjectOf(body.params) ?? {};
614
+ try {
615
+ const result = await this.callCollabAction(action, params);
616
+ const response = { ok: true, trace_id: traceId, action, result: jsonSafe(result) };
617
+ this.recordTrace(traceId, { stage: 'collab_call', action, result: response });
618
+ sendJson(res, 200, response);
619
+ }
620
+ catch (err) {
621
+ const error = {
622
+ ok: false,
623
+ trace_id: traceId,
624
+ action,
625
+ error_code: err instanceof Error ? err.name : 'Error',
626
+ error_message: err instanceof Error ? err.message : String(err),
627
+ };
628
+ this.recordTrace(traceId, { stage: 'collab_call_error', action, error });
629
+ sendJson(res, 500, error);
630
+ }
631
+ }
632
+ async storageCall(req, res) {
633
+ const body = await readJson(req);
634
+ const traceId = textOf(body.trace_id || crypto.randomUUID().replace(/-/g, ''));
635
+ const action = textOf(body.action).trim();
636
+ const params = jsonObjectOf(body.params) ?? {};
637
+ try {
638
+ const result = await this.callStorageAction(action, params);
639
+ const response = { ok: true, trace_id: traceId, action, result: jsonSafe(result) };
640
+ this.recordTrace(traceId, { stage: 'storage_call', action, result: response });
641
+ sendJson(res, 200, response);
642
+ }
643
+ catch (err) {
644
+ const error = {
645
+ ok: false,
646
+ trace_id: traceId,
647
+ action,
648
+ error_code: err instanceof Error ? err.name : 'Error',
649
+ error_message: err instanceof Error ? err.message : String(err),
650
+ };
651
+ this.recordTrace(traceId, { stage: 'storage_call_error', action, error });
652
+ sendJson(res, 500, error);
653
+ }
654
+ }
655
+ async callCollabAction(action, params) {
656
+ const collabRoot = textOf(params.collab_root ?? params.collabRoot);
657
+ const doc = textOf(params.doc);
658
+ const source = textOf(params.source);
659
+ switch (action) {
660
+ case 'ls':
661
+ case 'ls-files':
662
+ return await this.client.collab.lsFiles(collabRoot);
663
+ case 'create':
664
+ return await this.client.collab.create(collabRoot, doc, source);
665
+ case 'read':
666
+ return await this.client.collab.show(collabRoot, doc);
667
+ case 'show':
668
+ return await this.client.collab.show(collabRoot, doc, params.rev == null ? undefined : Number(params.rev) || 0);
669
+ case 'submit':
670
+ return await this.client.collab.commit(collabRoot, doc, source, Number(params.onto ?? params.base_version ?? params.baseVersion ?? 0) || 0, textOf(params.message) || '');
671
+ case 'commit':
672
+ return await this.client.collab.commit(collabRoot, doc, source, Number(params.onto ?? params.base_version ?? params.baseVersion ?? 0) || 0, textOf(params.message) || '');
673
+ case 'merge':
674
+ return await this.client.collab.merge(collabRoot, doc, source, Number(params.onto ?? params.base_version ?? params.baseVersion ?? 0) || 0);
675
+ case 'history':
676
+ case 'log':
677
+ return await this.client.collab.log(collabRoot, doc);
678
+ case 'get':
679
+ return await this.client.collab.show(collabRoot, doc, Number(params.version ?? 0) || 0);
680
+ case 'diff':
681
+ return await this.client.collab.diff(collabRoot, doc, Number(params.from ?? 0) || 0, Number(params.to ?? 0) || 0);
682
+ case 'export':
683
+ return await this.client.collab.clone(collabRoot, textOf(params.dest), false);
684
+ case 'adopt':
685
+ return await this.client.collab.clone(textOf(params.src), textOf(params.new_root ?? params.newRoot), true);
686
+ case 'clone':
687
+ return await this.client.collab.clone(textOf(params.src), textOf(params.dest), Boolean(params.reroot));
688
+ case 'prune':
689
+ return await this.client.collab.prune(collabRoot, doc);
690
+ case 'gc':
691
+ return await this.client.collab.gc(collabRoot, params.dry_run == null && params.dryRun == null ? true : Boolean(params.dry_run ?? params.dryRun));
692
+ case 'reflog':
693
+ return await this.client.collab.reflog(collabRoot, doc || undefined, Number(params.limit ?? 100) || 100);
694
+ case 'reset':
695
+ return await this.client.collab.revert(collabRoot, doc, Number(params.version ?? 0) || 0, textOf(params.message) || '');
696
+ case 'revert':
697
+ return await this.client.collab.revert(collabRoot, doc, Number(params.rev ?? params.version ?? 0) || 0, textOf(params.message) || '');
698
+ case 'discover':
699
+ case 'ls-remote':
700
+ return await this.client.collab.lsRemote(textOf(params.group_aid ?? params.groupAid));
701
+ case 'unregister':
702
+ return await this.client.collab.unregister(textOf(params.group_aid ?? params.groupAid), collabRoot);
703
+ case 'set_acl':
704
+ return await this.client.collab.setAcl(collabRoot, textOf(params.grantee_aid ?? params.granteeAID), {
705
+ perms: textOf(params.perms || 'w'),
706
+ expires_at: params.expires_at == null && params.expiresAt == null ? undefined : Number(params.expires_at ?? params.expiresAt),
707
+ max_uses: params.max_uses == null && params.maxUses == null ? undefined : Number(params.max_uses ?? params.maxUses),
708
+ });
709
+ case 'remove_acl':
710
+ return await this.client.collab.removeAcl(collabRoot, textOf(params.grantee_aid ?? params.granteeAID));
711
+ case 'snapshot.create':
712
+ case 'tag.create':
713
+ return await this.client.collab.tag.create(collabRoot, {
714
+ message: textOf(params.message),
715
+ major: Boolean(params.major),
716
+ });
717
+ case 'snapshot.list':
718
+ case 'tag.list':
719
+ return await this.client.collab.tag.list(collabRoot);
720
+ case 'snapshot.show':
721
+ case 'tag.show':
722
+ return await this.client.collab.tag.show(collabRoot, textOf(params.version));
723
+ case 'snapshot.diff':
724
+ case 'tag.diff':
725
+ return await this.client.collab.tag.diff(collabRoot, textOf(params.version_a ?? params.versionA), textOf(params.version_b ?? params.versionB));
726
+ case 'snapshot.restore':
727
+ case 'tag.restore':
728
+ return await this.client.collab.tag.restore(collabRoot, textOf(params.version), { message: textOf(params.message) });
729
+ case 'snapshot.rm':
730
+ case 'tag.rm':
731
+ return await this.client.collab.tag.rm(collabRoot, textOf(params.version));
732
+ case 'snapshot.prune':
733
+ case 'tag.prune':
734
+ return await this.client.collab.tag.prune(collabRoot, {
735
+ before: params.before == null ? null : Number(params.before),
736
+ keep_last: params.keep_last == null && params.keepLast == null ? null : Number(params.keep_last ?? params.keepLast),
737
+ });
738
+ default:
739
+ throw new Error(`unsupported collab action: ${action}`);
740
+ }
741
+ }
742
+ async callGroupFsAction(action, params, asGroupAid = '') {
743
+ const groupFs = this.client.group.fs;
744
+ let signingStore = null;
745
+ const withSigning = (source) => {
746
+ const next = { ...source };
747
+ if (asGroupAid) {
748
+ signingStore ??= this.aidStore();
749
+ next.signAs = asGroupAid;
750
+ next.aidStore = signingStore;
751
+ }
752
+ return next;
753
+ };
754
+ const rawCall = async (method, source) => {
755
+ const payload = { ...source };
756
+ if (asGroupAid) {
757
+ signingStore ??= this.aidStore();
758
+ const loaded = await signingStore.load(asGroupAid);
759
+ if (!loaded.ok || !loaded.data?.aid) {
760
+ throw new Error(loaded.error?.message || `signer identity not found: ${asGroupAid}`);
761
+ }
762
+ payload._client_signature_identity = loaded.data.aid;
763
+ }
764
+ return await this.client.call(method, payload);
765
+ };
766
+ const path = textOf(params.path).trim();
767
+ const options = withSigning(params);
768
+ delete options.path;
769
+ try {
770
+ switch (action) {
771
+ case 'ls':
772
+ return await groupFs.ls(path, options);
773
+ case 'find':
774
+ return await groupFs.find(path, options);
775
+ case 'stat':
776
+ return await groupFs.stat(path, options);
777
+ case 'lstat':
778
+ return await groupFs.lstat(path, options);
779
+ case 'mkdir':
780
+ return await groupFs.mkdir(path, { ...options, parents: Boolean(params.parents) });
781
+ case 'set_acl':
782
+ return await groupFs.setAcl(path, {
783
+ ...options,
784
+ grantee_aid: textOf(params.grantee_aid ?? params.granteeAid).trim() || 'role:admin',
785
+ perms: textOf(params.perms).trim() || 'rwx',
786
+ });
787
+ case 'remove_acl':
788
+ return await groupFs.removeAcl(path, {
789
+ ...options,
790
+ grantee_aid: textOf(params.grantee_aid ?? params.granteeAid).trim() || 'role:admin',
791
+ });
792
+ case 'get_acl':
793
+ return await groupFs.getAcl(path, options);
794
+ case 'list_acl':
795
+ return await groupFs.listAcl(path, options);
796
+ case 'rm':
797
+ return await groupFs.rm(path, {
798
+ ...options,
799
+ recursive: Boolean(params.recursive),
800
+ force: Boolean(params.force),
801
+ });
802
+ case 'cp': {
803
+ let src = textOf(params.src);
804
+ const dst = textOf(params.dst);
805
+ const cpOptions = withSigning(params);
806
+ delete cpOptions.src;
807
+ delete cpOptions.dst;
808
+ delete cpOptions.src_text;
809
+ if (params.src_text != null) {
810
+ src = this.writeTempText(textOf(params.src_text), '.txt');
811
+ }
812
+ const result = await groupFs.cp(src, dst, cpOptions);
813
+ return this.groupFsCpResponse(result, dst);
814
+ }
815
+ case 'mv':
816
+ {
817
+ const mvOptions = withSigning(params);
818
+ delete mvOptions.src;
819
+ delete mvOptions.dst;
820
+ return await groupFs.mv(textOf(params.src), textOf(params.dst), mvOptions);
821
+ }
822
+ case 'df':
823
+ return await groupFs.df(path || textOf(params.group_id), options);
824
+ case 'mount':
825
+ return await groupFs.mount(path, options);
826
+ case 'umount':
827
+ return await groupFs.umount(path, options);
828
+ case 'raw':
829
+ return await rawCall(textOf(params.method), withoutKeys(params, ['method']));
830
+ case 'check_upload':
831
+ return await rawCall('group.fs.check_upload', params);
832
+ case 'create_upload_session':
833
+ return await rawCall('group.fs.create_upload_session', params);
834
+ case 'complete_upload':
835
+ return await rawCall('group.fs.complete_upload', params);
836
+ case 'create_download_ticket':
837
+ return await rawCall('group.fs.create_download_ticket', params);
838
+ default:
839
+ throw new Error(`unsupported group fs action: ${action}`);
840
+ }
841
+ }
842
+ finally {
843
+ const storeToClose = signingStore;
844
+ if (storeToClose)
845
+ storeToClose.close();
846
+ }
847
+ }
848
+ writeTempText(content, suffix = '') {
849
+ const root = textOf(process.env.AUN_CROSS_SDK_TMP || '/tmp/aun-cross-sdk');
850
+ fs.mkdirSync(root, { recursive: true });
851
+ const filePath = `${root}/${crypto.randomUUID()}${suffix}`;
852
+ fs.writeFileSync(filePath, content, 'utf-8');
853
+ return filePath;
854
+ }
855
+ groupFsCpResponse(result, dst) {
856
+ const response = { raw: jsonSafe(result) };
857
+ const resultObj = jsonObjectOf(result);
858
+ const data = resultObj?.data;
859
+ if (data instanceof ArrayBuffer) {
860
+ const buffer = Buffer.from(new Uint8Array(data));
861
+ response.content = buffer.toString('utf-8');
862
+ response.content_base64 = buffer.toString('base64');
863
+ response.size_bytes = buffer.byteLength;
864
+ }
865
+ else if (data instanceof Uint8Array || ArrayBuffer.isView(data)) {
866
+ const view = data;
867
+ const buffer = Buffer.from(view.buffer, view.byteOffset, view.byteLength);
868
+ response.content = buffer.toString('utf-8');
869
+ response.content_base64 = buffer.toString('base64');
870
+ response.size_bytes = buffer.byteLength;
871
+ }
872
+ const localPath = textOf(resultObj?.localPath ?? resultObj?.local_path ?? dst).trim();
873
+ if (localPath && fs.existsSync(localPath) && fs.statSync(localPath).isFile()) {
874
+ const buffer = fs.readFileSync(localPath);
875
+ response.local_path = localPath;
876
+ response.content = buffer.toString('utf-8');
877
+ response.content_base64 = buffer.toString('base64');
878
+ response.size_bytes = buffer.byteLength;
879
+ }
880
+ return response;
881
+ }
882
+ async callStorageAction(action, params) {
883
+ const storage = this.client.storage;
884
+ const path = textOf(params.path).trim();
885
+ const owner = textOf(params.owner_aid ?? params.ownerAID).trim() || undefined;
886
+ const bucket = textOf(params.bucket).trim() || 'default';
887
+ const token = textOf(params.token).trim() || undefined;
888
+ const src = textOf(params.src).trim();
889
+ const dst = textOf(params.dst).trim();
890
+ const objectKey = textOf(params.object_key ?? params.objectKey ?? path).replace(/^\/+/, '');
891
+ switch (action) {
892
+ case 'write_bytes':
893
+ return await storage.writeBytes(path, params.content_base64 || params.contentBase64
894
+ ? Buffer.from(textOf(params.content), 'base64')
895
+ : textOf(params.content), {
896
+ owner,
897
+ bucket,
898
+ contentType: textOf(params.content_type ?? params.contentType).trim() || 'text/plain',
899
+ public: Boolean(params.public),
900
+ overwrite: params.overwrite == null ? false : Boolean(params.overwrite),
901
+ });
902
+ case 'read_bytes': {
903
+ const data = await storage.readBytes(path, { owner, bucket, token });
904
+ return {
905
+ content: Buffer.from(data).toString('utf-8'),
906
+ content_base64: Buffer.from(data).toString('base64'),
907
+ size_bytes: data.byteLength,
908
+ };
909
+ }
910
+ case 'create_download_ticket': {
911
+ return await storage.lowlevel.createDownloadTicket({ owner, bucket, objectKey, token });
912
+ }
913
+ case 'download_text': {
914
+ const url = textOf(params.url ?? params.download_url ?? params.downloadUrl).trim();
915
+ if (!url)
916
+ throw new Error('download_text requires url');
917
+ return { content: await downloadText(url, accessTokenFromClient(this.client)) };
918
+ }
919
+ case 'set_acl':
920
+ return await storage.setAcl(path, {
921
+ owner,
922
+ bucket,
923
+ granteeAid: textOf(params.grantee_aid ?? params.granteeAID).trim(),
924
+ perms: textOf(params.perms).trim(),
925
+ expiresAt: params.expires_at == null && params.expiresAt == null ? undefined : Number(params.expires_at ?? params.expiresAt),
926
+ maxUses: params.max_uses == null && params.maxUses == null ? undefined : Number(params.max_uses ?? params.maxUses),
927
+ });
928
+ case 'remove_acl':
929
+ return await storage.removeAcl(path, {
930
+ owner,
931
+ bucket,
932
+ granteeAid: textOf(params.grantee_aid ?? params.granteeAID).trim(),
933
+ });
934
+ case 'list':
935
+ return await storage.list(path, {
936
+ owner,
937
+ bucket,
938
+ page: Number(params.page ?? 1) || 1,
939
+ size: Number(params.size ?? 100) || 100,
940
+ marker: textOf(params.marker).trim() || undefined,
941
+ long: Boolean(params.long),
942
+ recursive: Boolean(params.recursive),
943
+ token,
944
+ });
945
+ case 'find':
946
+ return await storage.find(path, {
947
+ owner,
948
+ bucket,
949
+ name: textOf(params.name).trim() || undefined,
950
+ nodeType: textOf(params.node_type ?? params.nodeType).trim() || undefined,
951
+ size: textOf(params.size_expr ?? params.sizeExpr).trim() || undefined,
952
+ mtime: textOf(params.mtime).trim() || undefined,
953
+ page: Number(params.page ?? 1) || 1,
954
+ pageSize: Number(params.page_size ?? params.pageSize ?? 1000) || 1000,
955
+ token,
956
+ });
957
+ case 'stat':
958
+ return await storage.stat(path, { owner, bucket, token });
959
+ case 'lstat':
960
+ return await storage.lstat(path, { owner, bucket, token });
961
+ case 'mkdir':
962
+ return await storage.mkdir(path, { owner, bucket, parents: Boolean(params.parents) });
963
+ case 'touch':
964
+ return await storage.touch(path, {
965
+ owner,
966
+ bucket,
967
+ parents: Boolean(params.parents),
968
+ noCreate: Boolean(params.no_create ?? params.noCreate),
969
+ mtime: params.mtime == null ? undefined : Number(params.mtime),
970
+ followSymlinks: Boolean(params.follow_symlinks ?? params.followSymlinks),
971
+ });
972
+ case 'remove':
973
+ return await storage.remove(path, { owner, bucket, recursive: Boolean(params.recursive) });
974
+ case 'rename':
975
+ return await storage.rename(src, dst, {
976
+ owner,
977
+ bucket,
978
+ overwrite: Boolean(params.overwrite),
979
+ expectedVersion: params.expected_version == null && params.expectedVersion == null ? undefined : Number(params.expected_version ?? params.expectedVersion),
980
+ });
981
+ case 'copy':
982
+ return await storage.copy(src, dst, {
983
+ owner,
984
+ bucket,
985
+ dstOwner: textOf(params.dst_owner_aid ?? params.dstOwnerAID ?? params.dstOwner).trim() || undefined,
986
+ dstBucket: textOf(params.dst_bucket ?? params.dstBucket).trim() || undefined,
987
+ overwrite: Boolean(params.overwrite),
988
+ followSymlinks: Boolean(params.follow_symlinks ?? params.followSymlinks),
989
+ recursive: Boolean(params.recursive),
990
+ });
991
+ case 'df':
992
+ return await storage.df({ owner, bucket });
993
+ case 'du':
994
+ return await storage.du(path, {
995
+ owner,
996
+ bucket,
997
+ maxDepth: params.max_depth == null && params.maxDepth == null ? undefined : Number(params.max_depth ?? params.maxDepth),
998
+ pageSize: Number(params.page_size ?? params.pageSize ?? 1000) || 1000,
999
+ token,
1000
+ });
1001
+ case 'symlink':
1002
+ return await storage.symlink(textOf(params.target), path, { owner, bucket, overwrite: Boolean(params.overwrite) });
1003
+ case 'readlink':
1004
+ return await storage.readlink(path, { owner, bucket });
1005
+ case 'repoint':
1006
+ return await storage.repoint(path, textOf(params.new_target ?? params.newTarget), {
1007
+ owner,
1008
+ bucket,
1009
+ expectedVersion: params.expected_version == null && params.expectedVersion == null ? undefined : Number(params.expected_version ?? params.expectedVersion),
1010
+ });
1011
+ case 'rename_symlink':
1012
+ return await storage.renameSymlink(src, dst, {
1013
+ owner,
1014
+ bucket,
1015
+ overwrite: Boolean(params.overwrite),
1016
+ expectedVersion: params.expected_version == null && params.expectedVersion == null ? undefined : Number(params.expected_version ?? params.expectedVersion),
1017
+ });
1018
+ case 'delete_symlink':
1019
+ return await storage.lowlevel.deleteSymlink({ owner, bucket, path: objectKey });
1020
+ case 'list_acl':
1021
+ return await storage.listAcl(path, { owner, bucket });
1022
+ case 'check_access':
1023
+ return await storage.checkAccess(path, {
1024
+ owner,
1025
+ bucket,
1026
+ operation: textOf(params.operation).trim() || 'read',
1027
+ token,
1028
+ followSymlinks: params.follow_symlinks == null && params.followSymlinks == null ? true : Boolean(params.follow_symlinks ?? params.followSymlinks),
1029
+ });
1030
+ case 'issue_token':
1031
+ return await storage.issueToken(path, {
1032
+ owner,
1033
+ bucket,
1034
+ expiresAt: params.expires_at == null && params.expiresAt == null ? undefined : Number(params.expires_at ?? params.expiresAt),
1035
+ maxReads: params.max_reads == null && params.maxReads == null ? undefined : Number(params.max_reads ?? params.maxReads),
1036
+ });
1037
+ case 'revoke_token':
1038
+ return await storage.revokeToken(path, { owner, bucket, token: textOf(params.token) });
1039
+ case 'list_tokens':
1040
+ return await storage.listTokens(path, { owner, bucket });
1041
+ case 'set_visibility': {
1042
+ const allowRoles = Array.isArray(params.allow_roles) ? params.allow_roles.map((item) => textOf(item)) : (Array.isArray(params.allowRoles) ? params.allowRoles.map((item) => textOf(item)) : undefined);
1043
+ return await storage.setVisibility(path, { owner, bucket, visibility: textOf(params.visibility).trim() || 'private', allowRoles });
1044
+ }
1045
+ case 'create_share_link': {
1046
+ const allowedAids = Array.isArray(params.allowed_aids) ? params.allowed_aids.map((item) => textOf(item)) : (Array.isArray(params.allowedAids) ? params.allowedAids.map((item) => textOf(item)) : undefined);
1047
+ return await storage.lowlevel.createShareLink({
1048
+ owner,
1049
+ bucket,
1050
+ objectKey,
1051
+ allowedAids,
1052
+ expireInSeconds: params.expire_in_seconds == null && params.expireInSeconds == null ? undefined : Number(params.expire_in_seconds ?? params.expireInSeconds),
1053
+ maxUses: params.max_uses == null && params.maxUses == null ? undefined : Number(params.max_uses ?? params.maxUses),
1054
+ });
1055
+ }
1056
+ case 'list_share_links':
1057
+ return await storage.lowlevel.listShareLinks({ owner, bucket, objectKey: objectKey || undefined });
1058
+ case 'revoke_share_link':
1059
+ return await storage.lowlevel.revokeShareLink({ shareId: textOf(params.share_id ?? params.shareId).trim() });
1060
+ case 'get_by_share': {
1061
+ const result = await storage.lowlevel.getByShare({ shareId: textOf(params.share_id ?? params.shareId).trim() });
1062
+ const resultObj = jsonObjectOf(result);
1063
+ const content = textOf(resultObj?.content);
1064
+ if (content) {
1065
+ try {
1066
+ const buffer = Buffer.from(content, 'base64');
1067
+ return { ...(resultObj ?? {}), content_text: buffer.toString('utf-8'), content_base64: buffer.toString('base64') };
1068
+ }
1069
+ catch {
1070
+ return result;
1071
+ }
1072
+ }
1073
+ return result;
1074
+ }
1075
+ case 'head_object':
1076
+ return await storage.lowlevel.headObject({ owner, bucket, objectKey, token });
1077
+ case 'list_objects':
1078
+ return await storage.lowlevel.listObjects({
1079
+ owner,
1080
+ bucket,
1081
+ prefix: textOf(params.prefix),
1082
+ page: Number(params.page ?? 1) || 1,
1083
+ size: Number(params.size ?? 100) || 100,
1084
+ marker: textOf(params.marker).trim() || undefined,
1085
+ });
1086
+ case 'list_prefixes':
1087
+ return await storage.lowlevel.listPrefixes({ owner, bucket, prefix: textOf(params.prefix), size: Number(params.size ?? 100) || 100 });
1088
+ case 'delete_object':
1089
+ return await storage.lowlevel.deleteObject({ owner, bucket, objectKey });
1090
+ case 'set_object_meta':
1091
+ return await storage.lowlevel.setObjectMeta({
1092
+ owner,
1093
+ bucket,
1094
+ objectKey,
1095
+ metadata: jsonObjectOf(params.metadata) ?? {},
1096
+ contentType: textOf(params.content_type ?? params.contentType).trim() || undefined,
1097
+ merge: params.merge == null ? true : Boolean(params.merge),
1098
+ expectedVersion: params.expected_version == null && params.expectedVersion == null ? undefined : Number(params.expected_version ?? params.expectedVersion),
1099
+ });
1100
+ case 'append_object':
1101
+ return await storage.lowlevel.appendObject({
1102
+ owner,
1103
+ bucket,
1104
+ objectKey,
1105
+ content: params.content_base64 || params.contentBase64 ? Buffer.from(textOf(params.content), 'base64') : Buffer.from(textOf(params.content), 'utf-8'),
1106
+ contentType: textOf(params.content_type ?? params.contentType).trim() || undefined,
1107
+ metadata: jsonObjectOf(params.metadata) ?? undefined,
1108
+ expectedVersion: params.expected_version == null && params.expectedVersion == null ? undefined : Number(params.expected_version ?? params.expectedVersion),
1109
+ isPublic: Boolean(params.public ?? params.isPublic),
1110
+ });
1111
+ case 'create_folder':
1112
+ return await storage.lowlevel.createFolder({ owner, bucket, path: objectKey, parents: Boolean(params.parents ?? params.mkdirs) });
1113
+ case 'list_children':
1114
+ return await storage.lowlevel.listChildren({
1115
+ owner,
1116
+ bucket,
1117
+ path: objectKey,
1118
+ nodeType: textOf(params.node_type ?? params.nodeType ?? params.type).trim() || 'all',
1119
+ page: Number(params.page ?? 1) || 1,
1120
+ size: Number(params.size ?? 50) || 50,
1121
+ orderBy: textOf(params.order_by ?? params.orderBy).trim() || undefined,
1122
+ order: textOf(params.order).trim() || undefined,
1123
+ includeMetadata: params.include_metadata == null && params.includeMetadata == null ? undefined : Boolean(params.include_metadata ?? params.includeMetadata),
1124
+ includeUrls: params.include_urls == null && params.includeUrls == null ? undefined : Boolean(params.include_urls ?? params.includeUrls),
1125
+ });
1126
+ case 'copy_object':
1127
+ return await storage.lowlevel.copyObject({
1128
+ owner,
1129
+ bucket,
1130
+ srcPath: textOf(params.src_path ?? params.srcPath ?? src).replace(/^\/+/, ''),
1131
+ dstPath: textOf(params.dst_path ?? params.dstPath ?? dst).replace(/^\/+/, ''),
1132
+ overwrite: Boolean(params.overwrite),
1133
+ });
1134
+ case 'move_object':
1135
+ return await storage.lowlevel.moveObject({
1136
+ owner,
1137
+ bucket,
1138
+ path: textOf(params.src_path ?? params.srcPath ?? src ?? objectKey).replace(/^\/+/, ''),
1139
+ dstParentPath: textOf(params.dst_parent_path ?? params.dstParentPath).replace(/^\/+/, '').replace(/\/+$/g, ''),
1140
+ newName: textOf(params.new_name ?? params.newName),
1141
+ overwrite: Boolean(params.overwrite),
1142
+ expectedVersion: params.expected_version == null && params.expectedVersion == null ? undefined : Number(params.expected_version ?? params.expectedVersion),
1143
+ });
1144
+ case 'batch_delete': {
1145
+ const items = Array.isArray(params.items) ? params.items.filter((item) => item && typeof item === 'object' && !Array.isArray(item)) : [];
1146
+ return await storage.lowlevel.batchDelete({ owner, bucket, items, recursive: Boolean(params.recursive) });
1147
+ }
1148
+ default:
1149
+ throw new Error(`unsupported storage action: ${action}`);
1150
+ }
1151
+ }
513
1152
  async groupReady(url, res) {
514
1153
  const groupId = textOf(url.searchParams.get('group_id') ?? '').trim();
515
1154
  const expected = textOf(url.searchParams.get('members') ?? this.aid)
@@ -664,6 +1303,74 @@ class CrossSdkTsAgent {
664
1303
  }
665
1304
  return '';
666
1305
  }
1306
+ extractGroupAid(result) {
1307
+ if (!result || typeof result !== 'object' || Array.isArray(result))
1308
+ return '';
1309
+ const obj = result;
1310
+ const group = jsonObjectOf(obj.group);
1311
+ return textOf(group?.group_aid ?? obj.group_aid).trim();
1312
+ }
1313
+ aidStore() {
1314
+ return new AIDStore({
1315
+ aunPath: this.aunPath,
1316
+ encryptionSeed: '',
1317
+ slotId: this.slotId,
1318
+ debug: this.debug,
1319
+ });
1320
+ }
1321
+ }
1322
+ function shouldForwardBearerOnRedirect(current, next) {
1323
+ if (current.origin === next.origin)
1324
+ return true;
1325
+ const currentHost = current.hostname.toLowerCase();
1326
+ const nextHost = next.hostname.toLowerCase();
1327
+ if (!nextHost.startsWith('storage.'))
1328
+ return false;
1329
+ const issuer = nextHost.slice('storage.'.length);
1330
+ return Boolean(issuer) && (currentHost === issuer || currentHost.endsWith(`.${issuer}`));
1331
+ }
1332
+ function downloadText(url, bearerToken = '', redirects = 0) {
1333
+ return new Promise((resolve, reject) => {
1334
+ const parsed = new URL(url);
1335
+ const client = parsed.protocol === 'https:' ? https : http;
1336
+ const headers = bearerToken ? { Authorization: `Bearer ${bearerToken}` } : undefined;
1337
+ const options = parsed.protocol === 'https:'
1338
+ ? { rejectUnauthorized: false, headers }
1339
+ : { headers };
1340
+ const req = client.get(parsed, options, (resp) => {
1341
+ const status = resp.statusCode ?? 0;
1342
+ const location = typeof resp.headers.location === 'string' ? resp.headers.location : '';
1343
+ if ([301, 302, 303, 307, 308].includes(status) && location) {
1344
+ resp.resume();
1345
+ if (redirects >= 5) {
1346
+ reject(new Error(`download redirect limit exceeded url=${url}`));
1347
+ return;
1348
+ }
1349
+ const nextUrl = new URL(location, parsed).toString();
1350
+ const nextBearer = bearerToken && shouldForwardBearerOnRedirect(parsed, new URL(nextUrl)) ? bearerToken : '';
1351
+ downloadText(nextUrl, nextBearer, redirects + 1).then(resolve, reject);
1352
+ return;
1353
+ }
1354
+ const chunks = [];
1355
+ resp.on('data', (chunk) => chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk)));
1356
+ resp.on('end', () => {
1357
+ if (status < 200 || status >= 300) {
1358
+ reject(new Error(`download failed status=${status} url=${url}`));
1359
+ return;
1360
+ }
1361
+ const content = Buffer.concat(chunks).toString('utf-8');
1362
+ if (!content) {
1363
+ reject(new Error(`download returned empty body status=${status} url=${url}`));
1364
+ return;
1365
+ }
1366
+ resolve(content);
1367
+ });
1368
+ });
1369
+ req.setTimeout(20000, () => {
1370
+ req.destroy(new Error('download timeout'));
1371
+ });
1372
+ req.on('error', reject);
1373
+ });
667
1374
  }
668
1375
  async function main() {
669
1376
  const agent = new CrossSdkTsAgent();