agent-bridge-aun 1.0.28 → 1.0.30
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/README.md +1 -1
- package/dist/src-ts/plugins/aun/attachments.js +30 -11
- package/dist/src-ts/plugins/aun/index.js +1 -1
- package/package.json +1 -1
- package/plugin.json +1 -1
package/README.md
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
|
|
11
11
|
该插件依赖 `@agentunion/fastaun`,要求 Node.js 22.16 或更高版本。
|
|
12
12
|
|
|
13
|
-
附件回复按图片、视频和普通文件分组发送。MIME 类型为 `video/*` 的附件使用 EvolCore 标准 `type: "video"` 消息,使支持视频预览的 Peer
|
|
13
|
+
附件回复按图片、视频和普通文件分组发送。MIME 类型为 `video/*` 的附件使用 EvolCore 标准 `type: "video"` 消息,使支持视频预览的 Peer 客户端显示播放器;保留原话题和请求引用。视频沿用 EvolCore 标准上传流程:通过 SDK 上传可公开读取的对象,发送不带分享 URL 的标准对象引用,便于接收端取得下载票据及播放器分段读取;持有对象地址者可读取视频。图片和普通文件继续使用仅原 Peer 可访问的限时分享。该流程由插件独立实现,不调用 `ec` 命令,也不改变各 Agent 插件的产物回传策略。
|
|
14
14
|
|
|
15
15
|
ABWeb 的 AUN 设置只展示已连接 AID,并按来源分组。成功注册并记录在插件 `created_aids` 中的 AID 属于本工程;共享密钥库中其余 AID 属于 EvolCore。旧版 `created-aids.json` 记录继续兼容。来源只用于展示,连接和关联由 AUN 插件直接管理。列表先显示已关联 Agent 的身份,各组按最近成功关联的时间倒序排列,时间相同或旧记录没有时间时按 AID 名称排序。关联时间保存在插件配置的 `binding_times` 中,刷新或重启后保留;旧记录不补造时间,再次关联成功后开始记录。
|
|
16
16
|
|
|
@@ -6,6 +6,7 @@ exports.downloadAunAttachments = downloadAunAttachments;
|
|
|
6
6
|
exports.downloadAunAttachment = downloadAunAttachment;
|
|
7
7
|
exports.uploadAunAttachments = uploadAunAttachments;
|
|
8
8
|
const node_crypto_1 = require("node:crypto");
|
|
9
|
+
const node_util_1 = require("node:util");
|
|
9
10
|
const attachments_1 = require("../../attachments");
|
|
10
11
|
const aidPattern = /^[a-z0-9][a-z0-9_-]{2,63}\.[a-z0-9-]+(?:\.[a-z0-9-]+)+$/;
|
|
11
12
|
const mimePattern = /^[A-Za-z0-9!#$&^_.+-]+\/[A-Za-z0-9!#$&^_.+-]+$/;
|
|
@@ -13,6 +14,21 @@ const imageTypes = new Set(["image/png", "image/jpeg", "image/webp"]);
|
|
|
13
14
|
function digest(data) { return (0, node_crypto_1.createHash)("sha256").update(data).digest("hex"); }
|
|
14
15
|
function validKey(key) { return /^[A-Za-z0-9._-]+(?:\/[A-Za-z0-9._-]+)*$/.test(key) && !key.split("/").some((part) => part === "." || part === ".."); }
|
|
15
16
|
function validHash(value) { return /^[a-f0-9]{64}$/i.test(value); }
|
|
17
|
+
function normalizedMime(value) {
|
|
18
|
+
if (value === undefined)
|
|
19
|
+
return;
|
|
20
|
+
if (typeof value !== "string" || /[\u0000-\u001f\u007f]/.test(value))
|
|
21
|
+
throw new Error("AUN 附件 MIME 类型无效");
|
|
22
|
+
if (!value.trim())
|
|
23
|
+
return;
|
|
24
|
+
try {
|
|
25
|
+
const type = new node_util_1.MIMEType(value).essence;
|
|
26
|
+
if (mimePattern.test(type))
|
|
27
|
+
return type;
|
|
28
|
+
}
|
|
29
|
+
catch { /* 统一报告无效类型。 */ }
|
|
30
|
+
throw new Error("AUN 附件 MIME 类型无效");
|
|
31
|
+
}
|
|
16
32
|
function validateReference(ref) {
|
|
17
33
|
if (!aidPattern.test(ref.ownerAid) || !/^[A-Za-z0-9_-][A-Za-z0-9._-]{0,63}$/.test(ref.bucket) || !validKey(ref.objectKey))
|
|
18
34
|
throw new Error("AUN 附件引用路径无效");
|
|
@@ -44,11 +60,9 @@ function parseAunAttachment(value) {
|
|
|
44
60
|
const bucket = item.bucket === undefined ? "default" : typeof item.bucket === "string" ? item.bucket : "";
|
|
45
61
|
const filename = (0, attachments_1.attachmentFilename)(typeof item.filename === "string" ? item.filename : objectKey);
|
|
46
62
|
const ref = { ownerAid, bucket, objectKey, filename };
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
ref.contentType = item.content_type.toLowerCase();
|
|
51
|
-
}
|
|
63
|
+
const contentType = normalizedMime(item.content_type);
|
|
64
|
+
if (contentType)
|
|
65
|
+
ref.contentType = contentType;
|
|
52
66
|
if (item.size_bytes !== undefined) {
|
|
53
67
|
if (typeof item.size_bytes !== "number")
|
|
54
68
|
throw new Error("AUN 附件大小无效");
|
|
@@ -82,10 +96,8 @@ function checkedMetadata(meta, ref) {
|
|
|
82
96
|
if ([meta.owner, meta.owner_aid].some((owner) => owner && owner !== ref.ownerAid) || meta.bucket && meta.bucket !== ref.bucket
|
|
83
97
|
|| [meta.path, meta.object_key].some((path) => path && path !== `/${ref.objectKey}` && path !== ref.objectKey))
|
|
84
98
|
throw new Error("AUN 附件元数据引用不一致");
|
|
85
|
-
const rawType = metadataValue(meta, "contentType", "content_type");
|
|
86
|
-
|
|
87
|
-
throw new Error("AUN 附件元数据 MIME 类型无效");
|
|
88
|
-
const contentType = typeof rawType === "string" && rawType ? rawType.toLowerCase() : ref.contentType ?? "application/octet-stream";
|
|
99
|
+
const rawType = normalizedMime(metadataValue(meta, "contentType", "content_type"));
|
|
100
|
+
const contentType = rawType ?? ref.contentType ?? "application/octet-stream";
|
|
89
101
|
if (ref.contentType && rawType && ref.contentType.toLowerCase() !== contentType)
|
|
90
102
|
throw new Error("AUN 附件 MIME 类型校验失败");
|
|
91
103
|
const sha256 = typeof meta.sha256 === "string" && meta.sha256 ? meta.sha256.toLowerCase() : undefined;
|
|
@@ -236,9 +248,16 @@ async function uploadAunAttachments(client, ownerAid, peerAid, items) {
|
|
|
236
248
|
const filename = (0, attachments_1.attachmentFilename)(item.filename);
|
|
237
249
|
const objectKey = `shared/${(0, node_crypto_1.randomUUID)()}/${filename.replace(/[^A-Za-z0-9._-]/g, "_")}`;
|
|
238
250
|
const sha256 = digest(item.data);
|
|
239
|
-
const
|
|
240
|
-
|
|
251
|
+
const contentType = item.contentType.toLowerCase();
|
|
252
|
+
// 视频播放器不携带 AID 凭据,沿用 EvolCore 的标准可读对象上传方式。
|
|
253
|
+
const video = contentType.startsWith("video/");
|
|
254
|
+
const ref = { ownerAid, bucket: "default", objectKey, filename, contentType, sizeBytes: item.data.byteLength, sha256 };
|
|
255
|
+
const uploaded = await client.storage.writeBytes(`/${objectKey}`, item.data, { contentType, public: video, overwrite: video });
|
|
241
256
|
checkedMetadata({ ...uploaded, size: uploaded.size ?? uploaded.size_bytes ?? item.data.byteLength }, ref);
|
|
257
|
+
if (video) {
|
|
258
|
+
result.push({ owner_aid: ownerAid, object_key: objectKey, filename, content_type: contentType, size_bytes: item.data.byteLength, sha256 });
|
|
259
|
+
continue;
|
|
260
|
+
}
|
|
242
261
|
const share = await client.storage.lowlevel.createShareLink({ owner: ownerAid, bucket: "default", objectKey, allowedAids: [peerAid], expireInSeconds: 86400 });
|
|
243
262
|
if (share.owner_aid && share.owner_aid !== ownerAid || share.bucket && share.bucket !== "default" || share.object_key && share.object_key !== objectKey)
|
|
244
263
|
throw new Error("AUN 附件分享对象不一致");
|
|
@@ -11,7 +11,7 @@ const node_url_1 = require("node:url");
|
|
|
11
11
|
const messages_1 = require("./messages");
|
|
12
12
|
const attachments_1 = require("./attachments");
|
|
13
13
|
const manifest = {
|
|
14
|
-
id: "aun", version: "1.0.
|
|
14
|
+
id: "aun", version: "1.0.30", type: "channel", displayName: "AUN 通道",
|
|
15
15
|
entry: "dist/src-ts/plugins/aun/index.js", apiVersion: "1", process: "in-process",
|
|
16
16
|
capabilities: ["channel", "channel.identity.create", "channel.receive", "channel.send", "health", "cli"],
|
|
17
17
|
configSchema: "config.schema.json",
|
package/package.json
CHANGED