@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.
- package/CHANGELOG.md +547 -393
- package/_packed_docs/CHANGELOG-validators.md +144 -0
- package/_packed_docs/CHANGELOG.md +547 -393
- package/_packed_docs/INDEX.md +159 -84
- package/_packed_docs/KITE_DOCS_GUIDE.md +48 -31
- package/_packed_docs/agent.md/SCHEMA.md +2 -0
- package/_packed_docs/agent.md/examples/codeagent-claudecode.md +2 -0
- package/_packed_docs/agent.md/examples/human-developer.md +2 -0
- package/_packed_docs/agent.md/examples/openclaw-lobster.md +2 -0
- package/_packed_docs/agent.md/examples/signed-openclaw-lobster.md +2 -0
- 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
- package/_packed_docs/cli/AUN-CLI/350/256/276/350/256/241/346/226/207/346/241/243.md +266 -686
- package/_packed_docs/cli/CLI/346/211/213/345/206/214.md +331 -0
- package/_packed_docs/design/2026-05-22-aun-rpc-trace-enhancement.md +2 -0
- 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
- 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
- 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
- package/_packed_docs/protocol/00-/346/200/273/350/247/210/344/270/216/345/210/206/345/261/202.md +2 -0
- 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
- 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
- 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
- package/_packed_docs/protocol/03-Gateway-/350/277/236/346/216/245/346/250/241/345/274/217.md +2 -0
- package/_packed_docs/protocol/04-Peer-/345/255/220/345/215/217/350/256/256.md +2 -0
- package/_packed_docs/protocol/05-Relay-/345/255/220/345/215/217/350/256/256.md +2 -0
- 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
- package/_packed_docs/protocol/08-AUN-E2EE-Group.md +296 -900
- package/_packed_docs/protocol/08-AUN-E2EE.md +2 -0
- package/_packed_docs/protocol/09-/345/256/211/345/205/250/350/200/203/350/231/221.md +2 -0
- package/_packed_docs/protocol/10-Group-/345/255/220/345/215/217/350/256/256.md +66 -173
- package/_packed_docs/protocol/11-Storage-/345/255/220/345/215/217/350/256/256.md +55 -0
- package/_packed_docs/protocol/12-Stream-/345/255/220/345/215/217/350/256/256.md +2 -0
- package/_packed_docs/protocol/13-Agent/350/241/214/344/270/272/350/247/204/350/214/203.md +2 -0
- 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
- 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
- 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
- package/_packed_docs/protocol/README.md +4 -1
- package/_packed_docs/protocol/agent.md/SCHEMA.md +2 -0
- package/_packed_docs/protocol/agent.md/examples/codeagent-claudecode.md +2 -0
- package/_packed_docs/protocol/agent.md/examples/human-developer.md +2 -0
- package/_packed_docs/protocol/agent.md/examples/openclaw-lobster.md +2 -0
- package/_packed_docs/protocol/aun-docs-guide.md +2 -0
- package/_packed_docs/protocol/index.md +10 -3
- 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
- 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
- package/_packed_docs/protocol//351/231/204/345/275/225A-/346/234/257/350/257/255/350/241/250.md +2 -0
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- package/_packed_docs/sdk/01-/345/277/253/351/200/237/345/274/200/345/247/213.md +2 -0
- package/_packed_docs/sdk/02-WebSocket/345/215/217/350/256/256.md +2 -0
- package/_packed_docs/sdk/03-/346/240/270/345/277/203/346/246/202/345/277/265.md +2 -0
- package/_packed_docs/sdk/04-/350/277/236/346/216/245/344/270/216/350/256/244/350/257/201.md +2 -0
- package/_packed_docs/sdk/05-E2EE/345/212/240/345/257/206/351/200/232/344/277/241.md +6 -252
- package/_packed_docs/sdk/06-API/346/211/213/345/206/214.md +219 -177
- package/_packed_docs/sdk/07-/351/224/231/350/257/257/345/244/204/347/220/206.md +4 -1
- package/_packed_docs/sdk/08-/346/234/200/344/275/263/345/256/236/350/267/265.md +2 -0
- package/_packed_docs/sdk/09-collab-rpc-manual.md +581 -0
- package/_packed_docs/sdk/09-custody-api-manual.md +2 -0
- package/_packed_docs/sdk/09-group-rpc-manual.md +301 -634
- package/_packed_docs/sdk/09-message-rpc-manual.md +2 -0
- package/_packed_docs/sdk/09-meta-rpc-manual.md +2 -0
- package/_packed_docs/sdk/09-payload-reference.md +2 -0
- package/_packed_docs/sdk/09-proxy-rpc-manual.md +2 -0
- package/_packed_docs/sdk/09-storage-rpc-manual.md +984 -274
- package/_packed_docs/sdk/09-stream-rpc-manual.md +2 -0
- package/_packed_docs/sdk/AUN_DOCS_GUIDE.md +36 -23
- 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
- package/_packed_docs/sdk/INDEX.md +47 -30
- package/_packed_docs/sdk/Notify/351/200/232/347/237/245/346/226/271/346/241/210.md +2 -0
- package/_packed_docs/sdk/README.md +17 -15
- package/dist/aid-store.d.ts +25 -0
- package/dist/aid-store.js +80 -0
- package/dist/aid-store.js.map +1 -1
- package/dist/client/delivery.d.ts +11 -0
- package/dist/client/delivery.js +208 -25
- package/dist/client/delivery.js.map +1 -1
- package/dist/client/group-state.js +33 -11
- package/dist/client/group-state.js.map +1 -1
- package/dist/client/rpc-pipeline.d.ts +1 -0
- package/dist/client/rpc-pipeline.js +177 -65
- package/dist/client/rpc-pipeline.js.map +1 -1
- package/dist/client/v2-e2ee.d.ts +6 -1
- package/dist/client/v2-e2ee.js +199 -130
- package/dist/client/v2-e2ee.js.map +1 -1
- package/dist/client.d.ts +37 -1
- package/dist/client.js +491 -44
- package/dist/client.js.map +1 -1
- package/dist/collab/client.d.ts +46 -0
- package/dist/collab/client.js +136 -0
- package/dist/collab/client.js.map +1 -0
- package/dist/collab/errors.d.ts +15 -0
- package/dist/collab/errors.js +60 -0
- package/dist/collab/errors.js.map +1 -0
- package/dist/collab/index.d.ts +3 -0
- package/dist/collab/index.js +4 -0
- package/dist/collab/index.js.map +1 -0
- package/dist/collab/types.d.ts +110 -0
- package/dist/collab/types.js +2 -0
- package/dist/collab/types.js.map +1 -0
- package/dist/crypto.d.ts +2 -0
- package/dist/crypto.js +6 -0
- package/dist/crypto.js.map +1 -1
- package/dist/errors.d.ts +0 -12
- package/dist/errors.js +9 -25
- package/dist/errors.js.map +1 -1
- package/dist/facades.d.ts +94 -0
- package/dist/facades.js +255 -0
- package/dist/facades.js.map +1 -0
- package/dist/group-fs.d.ts +122 -0
- package/dist/group-fs.js +467 -0
- package/dist/group-fs.js.map +1 -0
- package/dist/group-id.d.ts +9 -12
- package/dist/group-id.js +41 -63
- package/dist/group-id.js.map +1 -1
- package/dist/group-resources.d.ts +31 -0
- package/dist/group-resources.js +84 -0
- package/dist/group-resources.js.map +1 -0
- package/dist/index.d.ts +9 -3
- package/dist/index.js +11 -1
- package/dist/index.js.map +1 -1
- package/dist/keystore/aid-db.d.ts +1 -0
- package/dist/keystore/aid-db.js +43 -43
- package/dist/keystore/aid-db.js.map +1 -1
- package/dist/keystore/local-identity-store.d.ts +16 -0
- package/dist/keystore/local-identity-store.js +190 -18
- package/dist/keystore/local-identity-store.js.map +1 -1
- package/dist/keystore/local-token-store.d.ts +0 -13
- package/dist/keystore/local-token-store.js +0 -105
- package/dist/keystore/local-token-store.js.map +1 -1
- package/dist/logger.d.ts +2 -0
- package/dist/logger.js +4 -0
- package/dist/logger.js.map +1 -1
- package/dist/register-flow.d.ts +1 -0
- package/dist/register-flow.js +3 -0
- package/dist/register-flow.js.map +1 -1
- package/dist/service-proxy.d.ts +1 -0
- package/dist/service-proxy.js +17 -4
- package/dist/service-proxy.js.map +1 -1
- package/dist/storage/errors.d.ts +27 -0
- package/dist/storage/errors.js +65 -0
- package/dist/storage/errors.js.map +1 -0
- package/dist/storage/index.d.ts +1 -0
- package/dist/storage/index.js +2 -0
- package/dist/storage/index.js.map +1 -0
- package/dist/storage/lowlevel.d.ts +321 -0
- package/dist/storage/lowlevel.js +475 -0
- package/dist/storage/lowlevel.js.map +1 -0
- package/dist/storage/types.d.ts +57 -0
- package/dist/storage/types.js +116 -0
- package/dist/storage/types.js.map +1 -0
- package/dist/storage/vfs.d.ts +166 -0
- package/dist/storage/vfs.js +524 -0
- package/dist/storage/vfs.js.map +1 -0
- package/dist/tools/cross-sdk-agent.js +708 -1
- package/dist/tools/cross-sdk-agent.js.map +1 -1
- package/dist/transport.d.ts +5 -0
- package/dist/transport.js +124 -21
- package/dist/transport.js.map +1 -1
- package/dist/types.d.ts +38 -0
- package/dist/v2/session/session.d.ts +2 -0
- package/dist/v2/session/session.js +53 -23
- package/dist/v2/session/session.js.map +1 -1
- package/dist/v2/state/commitment.d.ts +1 -1
- package/dist/v2/state/commitment.js +4 -2
- package/dist/v2/state/commitment.js.map +1 -1
- package/dist/validators.d.ts +32 -0
- package/dist/validators.js +128 -0
- package/dist/validators.js.map +1 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/version.js.map +1 -1
- 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 =
|
|
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();
|