diff --git a/src/laana-v0.1.3/proto/entity/file.proto b/src/laana-v0.1.3/proto/entity/file.proto
deleted file mode 100644
index 41740eaf..00000000
--- a/src/laana-v0.1.3/proto/entity/file.proto
+++ /dev/null
@@ -1,10 +0,0 @@
-syntax = 'proto3';
-package Laana;
-
-message File {
-  oneof uri {
-    string url = 1;
-    string cacheId = 2;
-    bytes raw = 3;
-  }
-}
\ No newline at end of file
diff --git a/src/laana-v0.1.3/types/entity/file.ts b/src/laana-v0.1.3/types/entity/file.ts
deleted file mode 100644
index a607daa7..00000000
--- a/src/laana-v0.1.3/types/entity/file.ts
+++ /dev/null
@@ -1,111 +0,0 @@
-// @generated by protobuf-ts 2.9.4
-// @generated from protobuf file "entity/file.proto" (package "Laana", syntax proto3)
-// tslint:disable
-import type { BinaryWriteOptions } from "@protobuf-ts/runtime";
-import type { IBinaryWriter } from "@protobuf-ts/runtime";
-import { WireType } from "@protobuf-ts/runtime";
-import type { BinaryReadOptions } from "@protobuf-ts/runtime";
-import type { IBinaryReader } from "@protobuf-ts/runtime";
-import { UnknownFieldHandler } from "@protobuf-ts/runtime";
-import type { PartialMessage } from "@protobuf-ts/runtime";
-import { reflectionMergePartial } from "@protobuf-ts/runtime";
-import { MessageType } from "@protobuf-ts/runtime";
-/**
- * @generated from protobuf message Laana.File
- */
-export interface File {
-    /**
-     * @generated from protobuf oneof: uri
-     */
-    uri: {
-        oneofKind: "url";
-        /**
-         * @generated from protobuf field: string url = 1;
-         */
-        url: string;
-    } | {
-        oneofKind: "cacheId";
-        /**
-         * @generated from protobuf field: string cacheId = 2;
-         */
-        cacheId: string;
-    } | {
-        oneofKind: "raw";
-        /**
-         * @generated from protobuf field: bytes raw = 3;
-         */
-        raw: Uint8Array;
-    } | {
-        oneofKind: undefined;
-    };
-}
-// @generated message type with reflection information, may provide speed optimized methods
-class File$Type extends MessageType<File> {
-    constructor() {
-        super("Laana.File", [
-            { no: 1, name: "url", kind: "scalar", oneof: "uri", T: 9 /*ScalarType.STRING*/ },
-            { no: 2, name: "cacheId", kind: "scalar", oneof: "uri", T: 9 /*ScalarType.STRING*/ },
-            { no: 3, name: "raw", kind: "scalar", oneof: "uri", T: 12 /*ScalarType.BYTES*/ }
-        ]);
-    }
-    create(value?: PartialMessage<File>): File {
-        const message = globalThis.Object.create((this.messagePrototype!));
-        message.uri = { oneofKind: undefined };
-        if (value !== undefined)
-            reflectionMergePartial<File>(this, message, value);
-        return message;
-    }
-    internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: File): File {
-        let message = target ?? this.create(), end = reader.pos + length;
-        while (reader.pos < end) {
-            let [fieldNo, wireType] = reader.tag();
-            switch (fieldNo) {
-                case /* string url */ 1:
-                    message.uri = {
-                        oneofKind: "url",
-                        url: reader.string()
-                    };
-                    break;
-                case /* string cacheId */ 2:
-                    message.uri = {
-                        oneofKind: "cacheId",
-                        cacheId: reader.string()
-                    };
-                    break;
-                case /* bytes raw */ 3:
-                    message.uri = {
-                        oneofKind: "raw",
-                        raw: reader.bytes()
-                    };
-                    break;
-                default:
-                    let u = options.readUnknownField;
-                    if (u === "throw")
-                        throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
-                    let d = reader.skip(wireType);
-                    if (u !== false)
-                        (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
-            }
-        }
-        return message;
-    }
-    internalBinaryWrite(message: File, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
-        /* string url = 1; */
-        if (message.uri.oneofKind === "url")
-            writer.tag(1, WireType.LengthDelimited).string(message.uri.url);
-        /* string cacheId = 2; */
-        if (message.uri.oneofKind === "cacheId")
-            writer.tag(2, WireType.LengthDelimited).string(message.uri.cacheId);
-        /* bytes raw = 3; */
-        if (message.uri.oneofKind === "raw")
-            writer.tag(3, WireType.LengthDelimited).bytes(message.uri.raw);
-        let u = options.writeUnknownFields;
-        if (u !== false)
-            (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
-        return writer;
-    }
-}
-/**
- * @generated MessageType for protobuf message Laana.File
- */
-export const File = new File$Type();
diff --git a/src/laana-v0.1.3/action/index.ts b/src/laana-v0.2.0/action/index.ts
similarity index 88%
rename from src/laana-v0.1.3/action/index.ts
rename to src/laana-v0.2.0/action/index.ts
index bb523403..f8946a41 100644
--- a/src/laana-v0.1.3/action/index.ts
+++ b/src/laana-v0.2.0/action/index.ts
@@ -1,4 +1,4 @@
-import { ActionPing, ActionPong } from '@/laana-v0.1.3/types/action/wrapper';
+import { ActionPing, ActionPong } from '../types/action/wrapper';
 
 type ExtractFromPongOrVoid<key> = Extract<ActionPong['pong'], { oneofKind: key; }> extends never ?
     void :
diff --git a/src/laana-v0.1.3/action/message.ts b/src/laana-v0.2.0/action/message.ts
similarity index 92%
rename from src/laana-v0.1.3/action/message.ts
rename to src/laana-v0.2.0/action/message.ts
index 502c1c21..b79576b6 100644
--- a/src/laana-v0.1.3/action/message.ts
+++ b/src/laana-v0.2.0/action/message.ts
@@ -1,6 +1,6 @@
-import { NapCatLaanaAdapter } from '@/laana-v0.1.3';
+import { NapCatLaanaAdapter } from '..';
 import { NapCatCore } from '@/core';
-import { LaanaActionHandler } from '@/laana-v0.1.3/action/index';
+import { LaanaActionHandler } from '../action';
 import fs from 'fs';
 
 export class LaanaMessageActionHandler {
diff --git a/src/laana-v0.1.3/config/index.ts b/src/laana-v0.2.0/config/index.ts
similarity index 100%
rename from src/laana-v0.1.3/config/index.ts
rename to src/laana-v0.2.0/config/index.ts
diff --git a/src/laana-v0.1.3/config/laana.json b/src/laana-v0.2.0/config/laana.json
similarity index 100%
rename from src/laana-v0.1.3/config/laana.json
rename to src/laana-v0.2.0/config/laana.json
diff --git a/src/laana-v0.1.3/index.ts b/src/laana-v0.2.0/index.ts
similarity index 75%
rename from src/laana-v0.1.3/index.ts
rename to src/laana-v0.2.0/index.ts
index 15da0a48..e537d151 100644
--- a/src/laana-v0.1.3/index.ts
+++ b/src/laana-v0.2.0/index.ts
@@ -1,12 +1,12 @@
 import { InstanceContext, NapCatCore } from '@/core';
 import { NapCatPathWrapper } from '@/common/path';
-import { LaanaFileUtils } from '@/laana-v0.1.3/utils/file';
-import { LaanaMessageUtils } from '@/laana-v0.1.3/utils/message';
-import { LaanaActionHandler } from '@/laana-v0.1.3/action';
-import { LaanaMessageActionHandler } from '@/laana-v0.1.3/action/message';
-import { LaanaConfigLoader } from '@/laana-v0.1.3/config';
-import { LaanaNetworkManager } from '@/laana-v0.1.3/network';
-import { LaanaWsServerAdapter } from '@/laana-v0.1.3/network/ws-server';
+import { LaanaFileUtils } from './utils/file';
+import { LaanaMessageUtils } from './utils/message';
+import { LaanaActionHandler } from './action';
+import { LaanaMessageActionHandler } from './action/message';
+import { LaanaConfigLoader } from './config';
+import { LaanaNetworkManager } from './network';
+import { LaanaWsServerAdapter } from './network/ws-server';
 
 export class NapCatLaanaAdapter {
     utils = {
diff --git a/src/laana-v0.1.3/network/index.ts b/src/laana-v0.2.0/network/index.ts
similarity index 92%
rename from src/laana-v0.1.3/network/index.ts
rename to src/laana-v0.2.0/network/index.ts
index 7e894ad8..2d25638b 100644
--- a/src/laana-v0.1.3/network/index.ts
+++ b/src/laana-v0.2.0/network/index.ts
@@ -1,5 +1,5 @@
-import { NapCatLaanaAdapter } from '@/laana-v0.1.3';
-import { EventWrapper } from '@/laana-v0.1.3/types/event/wrapper';
+import { NapCatLaanaAdapter } from '..';
+import { EventWrapper } from '../types/event/wrapper';
 import { randomUUID } from 'crypto';
 
 export interface ILaanaNetworkAdapter {
diff --git a/src/laana-v0.1.3/network/ws-server.ts b/src/laana-v0.2.0/network/ws-server.ts
similarity index 95%
rename from src/laana-v0.1.3/network/ws-server.ts
rename to src/laana-v0.2.0/network/ws-server.ts
index 4bd20446..c47ed015 100644
--- a/src/laana-v0.1.3/network/ws-server.ts
+++ b/src/laana-v0.2.0/network/ws-server.ts
@@ -1,7 +1,7 @@
-import { ILaanaNetworkAdapter } from '@/laana-v0.1.3/network/index';
-import { NapCatLaanaAdapter } from '@/laana-v0.1.3';
-import { LaanaDataWrapper } from '@/laana-v0.1.3/types/laana';
-import { EventWrapper } from '@/laana-v0.1.3/types/event/wrapper';
+import { ILaanaNetworkAdapter } from '../network/index';
+import { NapCatLaanaAdapter } from '..';
+import { LaanaDataWrapper } from '../types/laana';
+import { EventWrapper } from '../types/event/wrapper';
 import { RawData, WebSocket, WebSocketServer } from 'ws';
 import { Mutex } from 'async-mutex';
 import { NapCatCore } from '@/core';
diff --git a/src/laana-v0.1.3/proto/action/contact.proto b/src/laana-v0.2.0/proto/action/contact.proto
similarity index 100%
rename from src/laana-v0.1.3/proto/action/contact.proto
rename to src/laana-v0.2.0/proto/action/contact.proto
diff --git a/src/laana-v0.1.3/proto/action/file.proto b/src/laana-v0.2.0/proto/action/file.proto
similarity index 72%
rename from src/laana-v0.1.3/proto/action/file.proto
rename to src/laana-v0.2.0/proto/action/file.proto
index 0b32667c..6cd839ca 100644
--- a/src/laana-v0.1.3/proto/action/file.proto
+++ b/src/laana-v0.2.0/proto/action/file.proto
@@ -31,27 +31,6 @@ message GetFileDataPong {
   bytes data = 1;
 }
 
-message GroupFile {
-  string cacheId = 1;
-  string name = 2;
-  uint64 size = 3;
-  uint32 businessId = 4;
-  string uploaderUin = 5;
-  uint32 uploadTime = 6;
-  uint32 modifyTime = 7;
-  uint32 downloadCount = 8;
-  optional uint32 lastModifyTime = 9;
-  optional uint32 expireTime = 10;
-}
-
-message GroupFolder {
-  string folderId = 1;
-  string name = 2;
-  string creatorUin = 5;
-  uint32 createTime = 6;
-  uint32 fileCount = 11;
-}
-
 message GetGroupFileListPing {
   string groupCode = 1;
   optional string folderId = 2;
diff --git a/src/laana-v0.1.3/proto/action/group.proto b/src/laana-v0.2.0/proto/action/group.proto
similarity index 100%
rename from src/laana-v0.1.3/proto/action/group.proto
rename to src/laana-v0.2.0/proto/action/group.proto
diff --git a/src/laana-v0.1.3/proto/action/message.proto b/src/laana-v0.2.0/proto/action/message.proto
similarity index 100%
rename from src/laana-v0.1.3/proto/action/message.proto
rename to src/laana-v0.2.0/proto/action/message.proto
diff --git a/src/laana-v0.1.3/proto/action/request.proto b/src/laana-v0.2.0/proto/action/request.proto
similarity index 100%
rename from src/laana-v0.1.3/proto/action/request.proto
rename to src/laana-v0.2.0/proto/action/request.proto
diff --git a/src/laana-v0.1.3/proto/action/wrapper.proto b/src/laana-v0.2.0/proto/action/wrapper.proto
similarity index 94%
rename from src/laana-v0.1.3/proto/action/wrapper.proto
rename to src/laana-v0.2.0/proto/action/wrapper.proto
index fc11da3c..df3b3380 100644
--- a/src/laana-v0.1.3/proto/action/wrapper.proto
+++ b/src/laana-v0.2.0/proto/action/wrapper.proto
@@ -55,9 +55,16 @@ message ActionPing {
     CreateGroupFolderPing createGroupFolder = 507;
     DeleteGroupFilePing deleteGroupFile = 508;
     DeleteGroupFolderPing deleteGroupFolder = 509;
+
+    ExtendedActionPing extendedAction = 9999;
   }
 }
 
+message ExtendedActionPing {
+  string actionName = 1;
+  bytes actionData = 2;
+}
+
 message GeneralSuccessPong {
   bool success = 1;
 }
@@ -115,5 +122,12 @@ message ActionPong {
     CreateGroupFolderPong createGroupFolder = 507;
     GeneralSuccessPong deleteGroupFile = 508;
     GeneralSuccessPong deleteGroupFolder = 509;
+
+    ExtendedActionPong extendedAction = 9999;
   }
+}
+
+message ExtendedActionPong {
+  string actionName = 1;
+  bytes pongData = 2;
 }
\ No newline at end of file
diff --git a/src/laana-v0.2.0/proto/entity/file.proto b/src/laana-v0.2.0/proto/entity/file.proto
new file mode 100644
index 00000000..beaa7695
--- /dev/null
+++ b/src/laana-v0.2.0/proto/entity/file.proto
@@ -0,0 +1,31 @@
+syntax = 'proto3';
+package Laana;
+
+message File {
+  oneof uri {
+    string url = 1;
+    string cacheId = 2;
+    bytes raw = 3;
+  }
+}
+
+message GroupFile {
+  string cacheId = 1;
+  string name = 2;
+  uint64 size = 3;
+  uint32 businessId = 4;
+  string uploaderUin = 5;
+  uint32 uploadTime = 6;
+  uint32 modifyTime = 7;
+  uint32 downloadCount = 8;
+  optional uint32 lastModifyTime = 9;
+  optional uint32 expireTime = 10;
+}
+
+message GroupFolder {
+  string folderId = 1;
+  string name = 2;
+  string creatorUin = 5;
+  uint32 createTime = 6;
+  uint32 fileCount = 11;
+}
\ No newline at end of file
diff --git a/src/laana-v0.1.3/proto/entity/group.proto b/src/laana-v0.2.0/proto/entity/group.proto
similarity index 100%
rename from src/laana-v0.1.3/proto/entity/group.proto
rename to src/laana-v0.2.0/proto/entity/group.proto
diff --git a/src/laana-v0.1.3/proto/entity/message.proto b/src/laana-v0.2.0/proto/entity/message.proto
similarity index 100%
rename from src/laana-v0.1.3/proto/entity/message.proto
rename to src/laana-v0.2.0/proto/entity/message.proto
diff --git a/src/laana-v0.1.3/proto/entity/user.proto b/src/laana-v0.2.0/proto/entity/user.proto
similarity index 100%
rename from src/laana-v0.1.3/proto/entity/user.proto
rename to src/laana-v0.2.0/proto/entity/user.proto
diff --git a/src/laana-v0.1.3/proto/event/buddy.proto b/src/laana-v0.2.0/proto/event/buddy.proto
similarity index 100%
rename from src/laana-v0.1.3/proto/event/buddy.proto
rename to src/laana-v0.2.0/proto/event/buddy.proto
diff --git a/src/laana-v0.1.3/proto/event/group.proto b/src/laana-v0.2.0/proto/event/group.proto
similarity index 100%
rename from src/laana-v0.1.3/proto/event/group.proto
rename to src/laana-v0.2.0/proto/event/group.proto
diff --git a/src/laana-v0.1.3/proto/event/request.proto b/src/laana-v0.2.0/proto/event/request.proto
similarity index 100%
rename from src/laana-v0.1.3/proto/event/request.proto
rename to src/laana-v0.2.0/proto/event/request.proto
diff --git a/src/laana-v0.1.3/proto/event/wrapper.proto b/src/laana-v0.2.0/proto/event/wrapper.proto
similarity index 91%
rename from src/laana-v0.1.3/proto/event/wrapper.proto
rename to src/laana-v0.2.0/proto/event/wrapper.proto
index 067b3fba..4349f32f 100644
--- a/src/laana-v0.1.3/proto/event/wrapper.proto
+++ b/src/laana-v0.2.0/proto/event/wrapper.proto
@@ -29,5 +29,12 @@ message EventWrapper {
     SomeoneRequestToAddBuddyEvent someoneRequestToAddBuddyEvent = 301;
     SomeoneRequestToJoinGroupEvent someoneRequestToJoinGroupEvent = 302;
     SelfInvitedToGroupEvent selfInvitedToGroupEvent = 303;
+
+    ExtendedEvent extendedEvent = 9999;
   }
+}
+
+message ExtendedEvent {
+  string eventName = 1;
+  bytes eventData = 2;
 }
\ No newline at end of file
diff --git a/src/laana-v0.1.3/proto/laana.proto b/src/laana-v0.2.0/proto/laana.proto
similarity index 60%
rename from src/laana-v0.1.3/proto/laana.proto
rename to src/laana-v0.2.0/proto/laana.proto
index a92aa927..37dedbd2 100644
--- a/src/laana-v0.1.3/proto/laana.proto
+++ b/src/laana-v0.2.0/proto/laana.proto
@@ -1,6 +1,7 @@
 syntax = 'proto3';
 package Laana;
 
+import 'entity/message.proto';
 import 'action/wrapper.proto';
 import 'event/wrapper.proto';
 
@@ -9,5 +10,13 @@ message LaanaDataWrapper {
     ActionPing actionPing = 1;
     ActionPong actionPong = 2;
     EventWrapper event = 3;
+    Message message = 4;
+
+    ExtendedData extendedData = 99;
   }
+}
+
+message ExtendedData {
+  string key = 1;
+  bytes value = 2;
 }
\ No newline at end of file
diff --git a/src/laana-v0.1.3/types/action/contact.ts b/src/laana-v0.2.0/types/action/contact.ts
similarity index 100%
rename from src/laana-v0.1.3/types/action/contact.ts
rename to src/laana-v0.2.0/types/action/contact.ts
diff --git a/src/laana-v0.1.3/types/action/file.ts b/src/laana-v0.2.0/types/action/file.ts
similarity index 78%
rename from src/laana-v0.1.3/types/action/file.ts
rename to src/laana-v0.2.0/types/action/file.ts
index 0ca77a85..f8ece08f 100644
--- a/src/laana-v0.1.3/types/action/file.ts
+++ b/src/laana-v0.2.0/types/action/file.ts
@@ -11,6 +11,8 @@ import type { PartialMessage } from "@protobuf-ts/runtime";
 import { reflectionMergePartial } from "@protobuf-ts/runtime";
 import { MessageType } from "@protobuf-ts/runtime";
 import { File } from "../entity/file";
+import { GroupFolder } from "../entity/file";
+import { GroupFile } from "../entity/file";
 /**
  * @generated from protobuf message Laana.UploadCachePing
  */
@@ -74,76 +76,6 @@ export interface GetFileDataPong {
      */
     data: Uint8Array;
 }
-/**
- * @generated from protobuf message Laana.GroupFile
- */
-export interface GroupFile {
-    /**
-     * @generated from protobuf field: string cacheId = 1;
-     */
-    cacheId: string;
-    /**
-     * @generated from protobuf field: string name = 2;
-     */
-    name: string;
-    /**
-     * @generated from protobuf field: uint64 size = 3;
-     */
-    size: bigint;
-    /**
-     * @generated from protobuf field: uint32 businessId = 4;
-     */
-    businessId: number;
-    /**
-     * @generated from protobuf field: string uploaderUin = 5;
-     */
-    uploaderUin: string;
-    /**
-     * @generated from protobuf field: uint32 uploadTime = 6;
-     */
-    uploadTime: number;
-    /**
-     * @generated from protobuf field: uint32 modifyTime = 7;
-     */
-    modifyTime: number;
-    /**
-     * @generated from protobuf field: uint32 downloadCount = 8;
-     */
-    downloadCount: number;
-    /**
-     * @generated from protobuf field: optional uint32 lastModifyTime = 9;
-     */
-    lastModifyTime?: number;
-    /**
-     * @generated from protobuf field: optional uint32 expireTime = 10;
-     */
-    expireTime?: number;
-}
-/**
- * @generated from protobuf message Laana.GroupFolder
- */
-export interface GroupFolder {
-    /**
-     * @generated from protobuf field: string folderId = 1;
-     */
-    folderId: string;
-    /**
-     * @generated from protobuf field: string name = 2;
-     */
-    name: string;
-    /**
-     * @generated from protobuf field: string creatorUin = 5;
-     */
-    creatorUin: string;
-    /**
-     * @generated from protobuf field: uint32 createTime = 6;
-     */
-    createTime: number;
-    /**
-     * @generated from protobuf field: uint32 fileCount = 11;
-     */
-    fileCount: number;
-}
 /**
  * @generated from protobuf message Laana.GetGroupFileListPing
  */
@@ -575,202 +507,6 @@ class GetFileDataPong$Type extends MessageType<GetFileDataPong> {
  */
 export const GetFileDataPong = new GetFileDataPong$Type();
 // @generated message type with reflection information, may provide speed optimized methods
-class GroupFile$Type extends MessageType<GroupFile> {
-    constructor() {
-        super("Laana.GroupFile", [
-            { no: 1, name: "cacheId", kind: "scalar", T: 9 /*ScalarType.STRING*/ },
-            { no: 2, name: "name", kind: "scalar", T: 9 /*ScalarType.STRING*/ },
-            { no: 3, name: "size", kind: "scalar", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ },
-            { no: 4, name: "businessId", kind: "scalar", T: 13 /*ScalarType.UINT32*/ },
-            { no: 5, name: "uploaderUin", kind: "scalar", T: 9 /*ScalarType.STRING*/ },
-            { no: 6, name: "uploadTime", kind: "scalar", T: 13 /*ScalarType.UINT32*/ },
-            { no: 7, name: "modifyTime", kind: "scalar", T: 13 /*ScalarType.UINT32*/ },
-            { no: 8, name: "downloadCount", kind: "scalar", T: 13 /*ScalarType.UINT32*/ },
-            { no: 9, name: "lastModifyTime", kind: "scalar", opt: true, T: 13 /*ScalarType.UINT32*/ },
-            { no: 10, name: "expireTime", kind: "scalar", opt: true, T: 13 /*ScalarType.UINT32*/ }
-        ]);
-    }
-    create(value?: PartialMessage<GroupFile>): GroupFile {
-        const message = globalThis.Object.create((this.messagePrototype!));
-        message.cacheId = "";
-        message.name = "";
-        message.size = 0n;
-        message.businessId = 0;
-        message.uploaderUin = "";
-        message.uploadTime = 0;
-        message.modifyTime = 0;
-        message.downloadCount = 0;
-        if (value !== undefined)
-            reflectionMergePartial<GroupFile>(this, message, value);
-        return message;
-    }
-    internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: GroupFile): GroupFile {
-        let message = target ?? this.create(), end = reader.pos + length;
-        while (reader.pos < end) {
-            let [fieldNo, wireType] = reader.tag();
-            switch (fieldNo) {
-                case /* string cacheId */ 1:
-                    message.cacheId = reader.string();
-                    break;
-                case /* string name */ 2:
-                    message.name = reader.string();
-                    break;
-                case /* uint64 size */ 3:
-                    message.size = reader.uint64().toBigInt();
-                    break;
-                case /* uint32 businessId */ 4:
-                    message.businessId = reader.uint32();
-                    break;
-                case /* string uploaderUin */ 5:
-                    message.uploaderUin = reader.string();
-                    break;
-                case /* uint32 uploadTime */ 6:
-                    message.uploadTime = reader.uint32();
-                    break;
-                case /* uint32 modifyTime */ 7:
-                    message.modifyTime = reader.uint32();
-                    break;
-                case /* uint32 downloadCount */ 8:
-                    message.downloadCount = reader.uint32();
-                    break;
-                case /* optional uint32 lastModifyTime */ 9:
-                    message.lastModifyTime = reader.uint32();
-                    break;
-                case /* optional uint32 expireTime */ 10:
-                    message.expireTime = reader.uint32();
-                    break;
-                default:
-                    let u = options.readUnknownField;
-                    if (u === "throw")
-                        throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
-                    let d = reader.skip(wireType);
-                    if (u !== false)
-                        (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
-            }
-        }
-        return message;
-    }
-    internalBinaryWrite(message: GroupFile, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
-        /* string cacheId = 1; */
-        if (message.cacheId !== "")
-            writer.tag(1, WireType.LengthDelimited).string(message.cacheId);
-        /* string name = 2; */
-        if (message.name !== "")
-            writer.tag(2, WireType.LengthDelimited).string(message.name);
-        /* uint64 size = 3; */
-        if (message.size !== 0n)
-            writer.tag(3, WireType.Varint).uint64(message.size);
-        /* uint32 businessId = 4; */
-        if (message.businessId !== 0)
-            writer.tag(4, WireType.Varint).uint32(message.businessId);
-        /* string uploaderUin = 5; */
-        if (message.uploaderUin !== "")
-            writer.tag(5, WireType.LengthDelimited).string(message.uploaderUin);
-        /* uint32 uploadTime = 6; */
-        if (message.uploadTime !== 0)
-            writer.tag(6, WireType.Varint).uint32(message.uploadTime);
-        /* uint32 modifyTime = 7; */
-        if (message.modifyTime !== 0)
-            writer.tag(7, WireType.Varint).uint32(message.modifyTime);
-        /* uint32 downloadCount = 8; */
-        if (message.downloadCount !== 0)
-            writer.tag(8, WireType.Varint).uint32(message.downloadCount);
-        /* optional uint32 lastModifyTime = 9; */
-        if (message.lastModifyTime !== undefined)
-            writer.tag(9, WireType.Varint).uint32(message.lastModifyTime);
-        /* optional uint32 expireTime = 10; */
-        if (message.expireTime !== undefined)
-            writer.tag(10, WireType.Varint).uint32(message.expireTime);
-        let u = options.writeUnknownFields;
-        if (u !== false)
-            (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
-        return writer;
-    }
-}
-/**
- * @generated MessageType for protobuf message Laana.GroupFile
- */
-export const GroupFile = new GroupFile$Type();
-// @generated message type with reflection information, may provide speed optimized methods
-class GroupFolder$Type extends MessageType<GroupFolder> {
-    constructor() {
-        super("Laana.GroupFolder", [
-            { no: 1, name: "folderId", kind: "scalar", T: 9 /*ScalarType.STRING*/ },
-            { no: 2, name: "name", kind: "scalar", T: 9 /*ScalarType.STRING*/ },
-            { no: 5, name: "creatorUin", kind: "scalar", T: 9 /*ScalarType.STRING*/ },
-            { no: 6, name: "createTime", kind: "scalar", T: 13 /*ScalarType.UINT32*/ },
-            { no: 11, name: "fileCount", kind: "scalar", T: 13 /*ScalarType.UINT32*/ }
-        ]);
-    }
-    create(value?: PartialMessage<GroupFolder>): GroupFolder {
-        const message = globalThis.Object.create((this.messagePrototype!));
-        message.folderId = "";
-        message.name = "";
-        message.creatorUin = "";
-        message.createTime = 0;
-        message.fileCount = 0;
-        if (value !== undefined)
-            reflectionMergePartial<GroupFolder>(this, message, value);
-        return message;
-    }
-    internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: GroupFolder): GroupFolder {
-        let message = target ?? this.create(), end = reader.pos + length;
-        while (reader.pos < end) {
-            let [fieldNo, wireType] = reader.tag();
-            switch (fieldNo) {
-                case /* string folderId */ 1:
-                    message.folderId = reader.string();
-                    break;
-                case /* string name */ 2:
-                    message.name = reader.string();
-                    break;
-                case /* string creatorUin */ 5:
-                    message.creatorUin = reader.string();
-                    break;
-                case /* uint32 createTime */ 6:
-                    message.createTime = reader.uint32();
-                    break;
-                case /* uint32 fileCount */ 11:
-                    message.fileCount = reader.uint32();
-                    break;
-                default:
-                    let u = options.readUnknownField;
-                    if (u === "throw")
-                        throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
-                    let d = reader.skip(wireType);
-                    if (u !== false)
-                        (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
-            }
-        }
-        return message;
-    }
-    internalBinaryWrite(message: GroupFolder, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
-        /* string folderId = 1; */
-        if (message.folderId !== "")
-            writer.tag(1, WireType.LengthDelimited).string(message.folderId);
-        /* string name = 2; */
-        if (message.name !== "")
-            writer.tag(2, WireType.LengthDelimited).string(message.name);
-        /* string creatorUin = 5; */
-        if (message.creatorUin !== "")
-            writer.tag(5, WireType.LengthDelimited).string(message.creatorUin);
-        /* uint32 createTime = 6; */
-        if (message.createTime !== 0)
-            writer.tag(6, WireType.Varint).uint32(message.createTime);
-        /* uint32 fileCount = 11; */
-        if (message.fileCount !== 0)
-            writer.tag(11, WireType.Varint).uint32(message.fileCount);
-        let u = options.writeUnknownFields;
-        if (u !== false)
-            (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
-        return writer;
-    }
-}
-/**
- * @generated MessageType for protobuf message Laana.GroupFolder
- */
-export const GroupFolder = new GroupFolder$Type();
-// @generated message type with reflection information, may provide speed optimized methods
 class GetGroupFileListPing$Type extends MessageType<GetGroupFileListPing> {
     constructor() {
         super("Laana.GetGroupFileListPing", [
diff --git a/src/laana-v0.1.3/types/action/group.ts b/src/laana-v0.2.0/types/action/group.ts
similarity index 100%
rename from src/laana-v0.1.3/types/action/group.ts
rename to src/laana-v0.2.0/types/action/group.ts
diff --git a/src/laana-v0.1.3/types/action/message.ts b/src/laana-v0.2.0/types/action/message.ts
similarity index 100%
rename from src/laana-v0.1.3/types/action/message.ts
rename to src/laana-v0.2.0/types/action/message.ts
diff --git a/src/laana-v0.1.3/types/action/request.ts b/src/laana-v0.2.0/types/action/request.ts
similarity index 100%
rename from src/laana-v0.1.3/types/action/request.ts
rename to src/laana-v0.2.0/types/action/request.ts
diff --git a/src/laana-v0.1.3/types/action/wrapper.ts b/src/laana-v0.2.0/types/action/wrapper.ts
similarity index 92%
rename from src/laana-v0.1.3/types/action/wrapper.ts
rename to src/laana-v0.2.0/types/action/wrapper.ts
index 84160fdb..356dd106 100644
--- a/src/laana-v0.1.3/types/action/wrapper.ts
+++ b/src/laana-v0.2.0/types/action/wrapper.ts
@@ -324,10 +324,29 @@ export interface ActionPing {
          * @generated from protobuf field: Laana.DeleteGroupFolderPing deleteGroupFolder = 509;
          */
         deleteGroupFolder: DeleteGroupFolderPing;
+    } | {
+        oneofKind: "extendedAction";
+        /**
+         * @generated from protobuf field: Laana.ExtendedActionPing extendedAction = 9999;
+         */
+        extendedAction: ExtendedActionPing;
     } | {
         oneofKind: undefined;
     };
 }
+/**
+ * @generated from protobuf message Laana.ExtendedActionPing
+ */
+export interface ExtendedActionPing {
+    /**
+     * @generated from protobuf field: string actionName = 1;
+     */
+    actionName: string;
+    /**
+     * @generated from protobuf field: bytes actionData = 2;
+     */
+    actionData: Uint8Array;
+}
 /**
  * @generated from protobuf message Laana.GeneralSuccessPong
  */
@@ -603,10 +622,29 @@ export interface ActionPong {
          * @generated from protobuf field: Laana.GeneralSuccessPong deleteGroupFolder = 509;
          */
         deleteGroupFolder: GeneralSuccessPong;
+    } | {
+        oneofKind: "extendedAction";
+        /**
+         * @generated from protobuf field: Laana.ExtendedActionPong extendedAction = 9999;
+         */
+        extendedAction: ExtendedActionPong;
     } | {
         oneofKind: undefined;
     };
 }
+/**
+ * @generated from protobuf message Laana.ExtendedActionPong
+ */
+export interface ExtendedActionPong {
+    /**
+     * @generated from protobuf field: string actionName = 1;
+     */
+    actionName: string;
+    /**
+     * @generated from protobuf field: bytes pongData = 2;
+     */
+    pongData: Uint8Array;
+}
 // @generated message type with reflection information, may provide speed optimized methods
 class ActionPing$Type extends MessageType<ActionPing> {
     constructor() {
@@ -651,7 +689,8 @@ class ActionPing$Type extends MessageType<ActionPing> {
             { no: 506, name: "uploadGroupFile", kind: "message", oneof: "ping", T: () => UploadGroupFilePing },
             { no: 507, name: "createGroupFolder", kind: "message", oneof: "ping", T: () => CreateGroupFolderPing },
             { no: 508, name: "deleteGroupFile", kind: "message", oneof: "ping", T: () => DeleteGroupFilePing },
-            { no: 509, name: "deleteGroupFolder", kind: "message", oneof: "ping", T: () => DeleteGroupFolderPing }
+            { no: 509, name: "deleteGroupFolder", kind: "message", oneof: "ping", T: () => DeleteGroupFolderPing },
+            { no: 9999, name: "extendedAction", kind: "message", oneof: "ping", T: () => ExtendedActionPing }
         ]);
     }
     create(value?: PartialMessage<ActionPing>): ActionPing {
@@ -910,6 +949,12 @@ class ActionPing$Type extends MessageType<ActionPing> {
                         deleteGroupFolder: DeleteGroupFolderPing.internalBinaryRead(reader, reader.uint32(), options, (message.ping as any).deleteGroupFolder)
                     };
                     break;
+                case /* Laana.ExtendedActionPing extendedAction */ 9999:
+                    message.ping = {
+                        oneofKind: "extendedAction",
+                        extendedAction: ExtendedActionPing.internalBinaryRead(reader, reader.uint32(), options, (message.ping as any).extendedAction)
+                    };
+                    break;
                 default:
                     let u = options.readUnknownField;
                     if (u === "throw")
@@ -1045,6 +1090,9 @@ class ActionPing$Type extends MessageType<ActionPing> {
         /* Laana.DeleteGroupFolderPing deleteGroupFolder = 509; */
         if (message.ping.oneofKind === "deleteGroupFolder")
             DeleteGroupFolderPing.internalBinaryWrite(message.ping.deleteGroupFolder, writer.tag(509, WireType.LengthDelimited).fork(), options).join();
+        /* Laana.ExtendedActionPing extendedAction = 9999; */
+        if (message.ping.oneofKind === "extendedAction")
+            ExtendedActionPing.internalBinaryWrite(message.ping.extendedAction, writer.tag(9999, WireType.LengthDelimited).fork(), options).join();
         let u = options.writeUnknownFields;
         if (u !== false)
             (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
@@ -1056,6 +1104,61 @@ class ActionPing$Type extends MessageType<ActionPing> {
  */
 export const ActionPing = new ActionPing$Type();
 // @generated message type with reflection information, may provide speed optimized methods
+class ExtendedActionPing$Type extends MessageType<ExtendedActionPing> {
+    constructor() {
+        super("Laana.ExtendedActionPing", [
+            { no: 1, name: "actionName", kind: "scalar", T: 9 /*ScalarType.STRING*/ },
+            { no: 2, name: "actionData", kind: "scalar", T: 12 /*ScalarType.BYTES*/ }
+        ]);
+    }
+    create(value?: PartialMessage<ExtendedActionPing>): ExtendedActionPing {
+        const message = globalThis.Object.create((this.messagePrototype!));
+        message.actionName = "";
+        message.actionData = new Uint8Array(0);
+        if (value !== undefined)
+            reflectionMergePartial<ExtendedActionPing>(this, message, value);
+        return message;
+    }
+    internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: ExtendedActionPing): ExtendedActionPing {
+        let message = target ?? this.create(), end = reader.pos + length;
+        while (reader.pos < end) {
+            let [fieldNo, wireType] = reader.tag();
+            switch (fieldNo) {
+                case /* string actionName */ 1:
+                    message.actionName = reader.string();
+                    break;
+                case /* bytes actionData */ 2:
+                    message.actionData = reader.bytes();
+                    break;
+                default:
+                    let u = options.readUnknownField;
+                    if (u === "throw")
+                        throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
+                    let d = reader.skip(wireType);
+                    if (u !== false)
+                        (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
+            }
+        }
+        return message;
+    }
+    internalBinaryWrite(message: ExtendedActionPing, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
+        /* string actionName = 1; */
+        if (message.actionName !== "")
+            writer.tag(1, WireType.LengthDelimited).string(message.actionName);
+        /* bytes actionData = 2; */
+        if (message.actionData.length)
+            writer.tag(2, WireType.LengthDelimited).bytes(message.actionData);
+        let u = options.writeUnknownFields;
+        if (u !== false)
+            (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
+        return writer;
+    }
+}
+/**
+ * @generated MessageType for protobuf message Laana.ExtendedActionPing
+ */
+export const ExtendedActionPing = new ExtendedActionPing$Type();
+// @generated message type with reflection information, may provide speed optimized methods
 class GeneralSuccessPong$Type extends MessageType<GeneralSuccessPong> {
     constructor() {
         super("Laana.GeneralSuccessPong", [
@@ -1194,7 +1297,8 @@ class ActionPong$Type extends MessageType<ActionPong> {
             { no: 506, name: "uploadGroupFile", kind: "message", oneof: "pong", T: () => UploadGroupFilePong },
             { no: 507, name: "createGroupFolder", kind: "message", oneof: "pong", T: () => CreateGroupFolderPong },
             { no: 508, name: "deleteGroupFile", kind: "message", oneof: "pong", T: () => GeneralSuccessPong },
-            { no: 509, name: "deleteGroupFolder", kind: "message", oneof: "pong", T: () => GeneralSuccessPong }
+            { no: 509, name: "deleteGroupFolder", kind: "message", oneof: "pong", T: () => GeneralSuccessPong },
+            { no: 9999, name: "extendedAction", kind: "message", oneof: "pong", T: () => ExtendedActionPong }
         ]);
     }
     create(value?: PartialMessage<ActionPong>): ActionPong {
@@ -1459,6 +1563,12 @@ class ActionPong$Type extends MessageType<ActionPong> {
                         deleteGroupFolder: GeneralSuccessPong.internalBinaryRead(reader, reader.uint32(), options, (message.pong as any).deleteGroupFolder)
                     };
                     break;
+                case /* Laana.ExtendedActionPong extendedAction */ 9999:
+                    message.pong = {
+                        oneofKind: "extendedAction",
+                        extendedAction: ExtendedActionPong.internalBinaryRead(reader, reader.uint32(), options, (message.pong as any).extendedAction)
+                    };
+                    break;
                 default:
                     let u = options.readUnknownField;
                     if (u === "throw")
@@ -1597,6 +1707,9 @@ class ActionPong$Type extends MessageType<ActionPong> {
         /* Laana.GeneralSuccessPong deleteGroupFolder = 509; */
         if (message.pong.oneofKind === "deleteGroupFolder")
             GeneralSuccessPong.internalBinaryWrite(message.pong.deleteGroupFolder, writer.tag(509, WireType.LengthDelimited).fork(), options).join();
+        /* Laana.ExtendedActionPong extendedAction = 9999; */
+        if (message.pong.oneofKind === "extendedAction")
+            ExtendedActionPong.internalBinaryWrite(message.pong.extendedAction, writer.tag(9999, WireType.LengthDelimited).fork(), options).join();
         let u = options.writeUnknownFields;
         if (u !== false)
             (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
@@ -1607,3 +1720,58 @@ class ActionPong$Type extends MessageType<ActionPong> {
  * @generated MessageType for protobuf message Laana.ActionPong
  */
 export const ActionPong = new ActionPong$Type();
+// @generated message type with reflection information, may provide speed optimized methods
+class ExtendedActionPong$Type extends MessageType<ExtendedActionPong> {
+    constructor() {
+        super("Laana.ExtendedActionPong", [
+            { no: 1, name: "actionName", kind: "scalar", T: 9 /*ScalarType.STRING*/ },
+            { no: 2, name: "pongData", kind: "scalar", T: 12 /*ScalarType.BYTES*/ }
+        ]);
+    }
+    create(value?: PartialMessage<ExtendedActionPong>): ExtendedActionPong {
+        const message = globalThis.Object.create((this.messagePrototype!));
+        message.actionName = "";
+        message.pongData = new Uint8Array(0);
+        if (value !== undefined)
+            reflectionMergePartial<ExtendedActionPong>(this, message, value);
+        return message;
+    }
+    internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: ExtendedActionPong): ExtendedActionPong {
+        let message = target ?? this.create(), end = reader.pos + length;
+        while (reader.pos < end) {
+            let [fieldNo, wireType] = reader.tag();
+            switch (fieldNo) {
+                case /* string actionName */ 1:
+                    message.actionName = reader.string();
+                    break;
+                case /* bytes pongData */ 2:
+                    message.pongData = reader.bytes();
+                    break;
+                default:
+                    let u = options.readUnknownField;
+                    if (u === "throw")
+                        throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
+                    let d = reader.skip(wireType);
+                    if (u !== false)
+                        (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
+            }
+        }
+        return message;
+    }
+    internalBinaryWrite(message: ExtendedActionPong, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
+        /* string actionName = 1; */
+        if (message.actionName !== "")
+            writer.tag(1, WireType.LengthDelimited).string(message.actionName);
+        /* bytes pongData = 2; */
+        if (message.pongData.length)
+            writer.tag(2, WireType.LengthDelimited).bytes(message.pongData);
+        let u = options.writeUnknownFields;
+        if (u !== false)
+            (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
+        return writer;
+    }
+}
+/**
+ * @generated MessageType for protobuf message Laana.ExtendedActionPong
+ */
+export const ExtendedActionPong = new ExtendedActionPong$Type();
diff --git a/src/laana-v0.2.0/types/entity/file.ts b/src/laana-v0.2.0/types/entity/file.ts
new file mode 100644
index 00000000..405ea569
--- /dev/null
+++ b/src/laana-v0.2.0/types/entity/file.ts
@@ -0,0 +1,377 @@
+// @generated by protobuf-ts 2.9.4
+// @generated from protobuf file "entity/file.proto" (package "Laana", syntax proto3)
+// tslint:disable
+import type { BinaryWriteOptions } from "@protobuf-ts/runtime";
+import type { IBinaryWriter } from "@protobuf-ts/runtime";
+import { WireType } from "@protobuf-ts/runtime";
+import type { BinaryReadOptions } from "@protobuf-ts/runtime";
+import type { IBinaryReader } from "@protobuf-ts/runtime";
+import { UnknownFieldHandler } from "@protobuf-ts/runtime";
+import type { PartialMessage } from "@protobuf-ts/runtime";
+import { reflectionMergePartial } from "@protobuf-ts/runtime";
+import { MessageType } from "@protobuf-ts/runtime";
+/**
+ * @generated from protobuf message Laana.File
+ */
+export interface File {
+    /**
+     * @generated from protobuf oneof: uri
+     */
+    uri: {
+        oneofKind: "url";
+        /**
+         * @generated from protobuf field: string url = 1;
+         */
+        url: string;
+    } | {
+        oneofKind: "cacheId";
+        /**
+         * @generated from protobuf field: string cacheId = 2;
+         */
+        cacheId: string;
+    } | {
+        oneofKind: "raw";
+        /**
+         * @generated from protobuf field: bytes raw = 3;
+         */
+        raw: Uint8Array;
+    } | {
+        oneofKind: undefined;
+    };
+}
+/**
+ * @generated from protobuf message Laana.GroupFile
+ */
+export interface GroupFile {
+    /**
+     * @generated from protobuf field: string cacheId = 1;
+     */
+    cacheId: string;
+    /**
+     * @generated from protobuf field: string name = 2;
+     */
+    name: string;
+    /**
+     * @generated from protobuf field: uint64 size = 3;
+     */
+    size: bigint;
+    /**
+     * @generated from protobuf field: uint32 businessId = 4;
+     */
+    businessId: number;
+    /**
+     * @generated from protobuf field: string uploaderUin = 5;
+     */
+    uploaderUin: string;
+    /**
+     * @generated from protobuf field: uint32 uploadTime = 6;
+     */
+    uploadTime: number;
+    /**
+     * @generated from protobuf field: uint32 modifyTime = 7;
+     */
+    modifyTime: number;
+    /**
+     * @generated from protobuf field: uint32 downloadCount = 8;
+     */
+    downloadCount: number;
+    /**
+     * @generated from protobuf field: optional uint32 lastModifyTime = 9;
+     */
+    lastModifyTime?: number;
+    /**
+     * @generated from protobuf field: optional uint32 expireTime = 10;
+     */
+    expireTime?: number;
+}
+/**
+ * @generated from protobuf message Laana.GroupFolder
+ */
+export interface GroupFolder {
+    /**
+     * @generated from protobuf field: string folderId = 1;
+     */
+    folderId: string;
+    /**
+     * @generated from protobuf field: string name = 2;
+     */
+    name: string;
+    /**
+     * @generated from protobuf field: string creatorUin = 5;
+     */
+    creatorUin: string;
+    /**
+     * @generated from protobuf field: uint32 createTime = 6;
+     */
+    createTime: number;
+    /**
+     * @generated from protobuf field: uint32 fileCount = 11;
+     */
+    fileCount: number;
+}
+// @generated message type with reflection information, may provide speed optimized methods
+class File$Type extends MessageType<File> {
+    constructor() {
+        super("Laana.File", [
+            { no: 1, name: "url", kind: "scalar", oneof: "uri", T: 9 /*ScalarType.STRING*/ },
+            { no: 2, name: "cacheId", kind: "scalar", oneof: "uri", T: 9 /*ScalarType.STRING*/ },
+            { no: 3, name: "raw", kind: "scalar", oneof: "uri", T: 12 /*ScalarType.BYTES*/ }
+        ]);
+    }
+    create(value?: PartialMessage<File>): File {
+        const message = globalThis.Object.create((this.messagePrototype!));
+        message.uri = { oneofKind: undefined };
+        if (value !== undefined)
+            reflectionMergePartial<File>(this, message, value);
+        return message;
+    }
+    internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: File): File {
+        let message = target ?? this.create(), end = reader.pos + length;
+        while (reader.pos < end) {
+            let [fieldNo, wireType] = reader.tag();
+            switch (fieldNo) {
+                case /* string url */ 1:
+                    message.uri = {
+                        oneofKind: "url",
+                        url: reader.string()
+                    };
+                    break;
+                case /* string cacheId */ 2:
+                    message.uri = {
+                        oneofKind: "cacheId",
+                        cacheId: reader.string()
+                    };
+                    break;
+                case /* bytes raw */ 3:
+                    message.uri = {
+                        oneofKind: "raw",
+                        raw: reader.bytes()
+                    };
+                    break;
+                default:
+                    let u = options.readUnknownField;
+                    if (u === "throw")
+                        throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
+                    let d = reader.skip(wireType);
+                    if (u !== false)
+                        (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
+            }
+        }
+        return message;
+    }
+    internalBinaryWrite(message: File, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
+        /* string url = 1; */
+        if (message.uri.oneofKind === "url")
+            writer.tag(1, WireType.LengthDelimited).string(message.uri.url);
+        /* string cacheId = 2; */
+        if (message.uri.oneofKind === "cacheId")
+            writer.tag(2, WireType.LengthDelimited).string(message.uri.cacheId);
+        /* bytes raw = 3; */
+        if (message.uri.oneofKind === "raw")
+            writer.tag(3, WireType.LengthDelimited).bytes(message.uri.raw);
+        let u = options.writeUnknownFields;
+        if (u !== false)
+            (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
+        return writer;
+    }
+}
+/**
+ * @generated MessageType for protobuf message Laana.File
+ */
+export const File = new File$Type();
+// @generated message type with reflection information, may provide speed optimized methods
+class GroupFile$Type extends MessageType<GroupFile> {
+    constructor() {
+        super("Laana.GroupFile", [
+            { no: 1, name: "cacheId", kind: "scalar", T: 9 /*ScalarType.STRING*/ },
+            { no: 2, name: "name", kind: "scalar", T: 9 /*ScalarType.STRING*/ },
+            { no: 3, name: "size", kind: "scalar", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ },
+            { no: 4, name: "businessId", kind: "scalar", T: 13 /*ScalarType.UINT32*/ },
+            { no: 5, name: "uploaderUin", kind: "scalar", T: 9 /*ScalarType.STRING*/ },
+            { no: 6, name: "uploadTime", kind: "scalar", T: 13 /*ScalarType.UINT32*/ },
+            { no: 7, name: "modifyTime", kind: "scalar", T: 13 /*ScalarType.UINT32*/ },
+            { no: 8, name: "downloadCount", kind: "scalar", T: 13 /*ScalarType.UINT32*/ },
+            { no: 9, name: "lastModifyTime", kind: "scalar", opt: true, T: 13 /*ScalarType.UINT32*/ },
+            { no: 10, name: "expireTime", kind: "scalar", opt: true, T: 13 /*ScalarType.UINT32*/ }
+        ]);
+    }
+    create(value?: PartialMessage<GroupFile>): GroupFile {
+        const message = globalThis.Object.create((this.messagePrototype!));
+        message.cacheId = "";
+        message.name = "";
+        message.size = 0n;
+        message.businessId = 0;
+        message.uploaderUin = "";
+        message.uploadTime = 0;
+        message.modifyTime = 0;
+        message.downloadCount = 0;
+        if (value !== undefined)
+            reflectionMergePartial<GroupFile>(this, message, value);
+        return message;
+    }
+    internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: GroupFile): GroupFile {
+        let message = target ?? this.create(), end = reader.pos + length;
+        while (reader.pos < end) {
+            let [fieldNo, wireType] = reader.tag();
+            switch (fieldNo) {
+                case /* string cacheId */ 1:
+                    message.cacheId = reader.string();
+                    break;
+                case /* string name */ 2:
+                    message.name = reader.string();
+                    break;
+                case /* uint64 size */ 3:
+                    message.size = reader.uint64().toBigInt();
+                    break;
+                case /* uint32 businessId */ 4:
+                    message.businessId = reader.uint32();
+                    break;
+                case /* string uploaderUin */ 5:
+                    message.uploaderUin = reader.string();
+                    break;
+                case /* uint32 uploadTime */ 6:
+                    message.uploadTime = reader.uint32();
+                    break;
+                case /* uint32 modifyTime */ 7:
+                    message.modifyTime = reader.uint32();
+                    break;
+                case /* uint32 downloadCount */ 8:
+                    message.downloadCount = reader.uint32();
+                    break;
+                case /* optional uint32 lastModifyTime */ 9:
+                    message.lastModifyTime = reader.uint32();
+                    break;
+                case /* optional uint32 expireTime */ 10:
+                    message.expireTime = reader.uint32();
+                    break;
+                default:
+                    let u = options.readUnknownField;
+                    if (u === "throw")
+                        throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
+                    let d = reader.skip(wireType);
+                    if (u !== false)
+                        (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
+            }
+        }
+        return message;
+    }
+    internalBinaryWrite(message: GroupFile, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
+        /* string cacheId = 1; */
+        if (message.cacheId !== "")
+            writer.tag(1, WireType.LengthDelimited).string(message.cacheId);
+        /* string name = 2; */
+        if (message.name !== "")
+            writer.tag(2, WireType.LengthDelimited).string(message.name);
+        /* uint64 size = 3; */
+        if (message.size !== 0n)
+            writer.tag(3, WireType.Varint).uint64(message.size);
+        /* uint32 businessId = 4; */
+        if (message.businessId !== 0)
+            writer.tag(4, WireType.Varint).uint32(message.businessId);
+        /* string uploaderUin = 5; */
+        if (message.uploaderUin !== "")
+            writer.tag(5, WireType.LengthDelimited).string(message.uploaderUin);
+        /* uint32 uploadTime = 6; */
+        if (message.uploadTime !== 0)
+            writer.tag(6, WireType.Varint).uint32(message.uploadTime);
+        /* uint32 modifyTime = 7; */
+        if (message.modifyTime !== 0)
+            writer.tag(7, WireType.Varint).uint32(message.modifyTime);
+        /* uint32 downloadCount = 8; */
+        if (message.downloadCount !== 0)
+            writer.tag(8, WireType.Varint).uint32(message.downloadCount);
+        /* optional uint32 lastModifyTime = 9; */
+        if (message.lastModifyTime !== undefined)
+            writer.tag(9, WireType.Varint).uint32(message.lastModifyTime);
+        /* optional uint32 expireTime = 10; */
+        if (message.expireTime !== undefined)
+            writer.tag(10, WireType.Varint).uint32(message.expireTime);
+        let u = options.writeUnknownFields;
+        if (u !== false)
+            (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
+        return writer;
+    }
+}
+/**
+ * @generated MessageType for protobuf message Laana.GroupFile
+ */
+export const GroupFile = new GroupFile$Type();
+// @generated message type with reflection information, may provide speed optimized methods
+class GroupFolder$Type extends MessageType<GroupFolder> {
+    constructor() {
+        super("Laana.GroupFolder", [
+            { no: 1, name: "folderId", kind: "scalar", T: 9 /*ScalarType.STRING*/ },
+            { no: 2, name: "name", kind: "scalar", T: 9 /*ScalarType.STRING*/ },
+            { no: 5, name: "creatorUin", kind: "scalar", T: 9 /*ScalarType.STRING*/ },
+            { no: 6, name: "createTime", kind: "scalar", T: 13 /*ScalarType.UINT32*/ },
+            { no: 11, name: "fileCount", kind: "scalar", T: 13 /*ScalarType.UINT32*/ }
+        ]);
+    }
+    create(value?: PartialMessage<GroupFolder>): GroupFolder {
+        const message = globalThis.Object.create((this.messagePrototype!));
+        message.folderId = "";
+        message.name = "";
+        message.creatorUin = "";
+        message.createTime = 0;
+        message.fileCount = 0;
+        if (value !== undefined)
+            reflectionMergePartial<GroupFolder>(this, message, value);
+        return message;
+    }
+    internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: GroupFolder): GroupFolder {
+        let message = target ?? this.create(), end = reader.pos + length;
+        while (reader.pos < end) {
+            let [fieldNo, wireType] = reader.tag();
+            switch (fieldNo) {
+                case /* string folderId */ 1:
+                    message.folderId = reader.string();
+                    break;
+                case /* string name */ 2:
+                    message.name = reader.string();
+                    break;
+                case /* string creatorUin */ 5:
+                    message.creatorUin = reader.string();
+                    break;
+                case /* uint32 createTime */ 6:
+                    message.createTime = reader.uint32();
+                    break;
+                case /* uint32 fileCount */ 11:
+                    message.fileCount = reader.uint32();
+                    break;
+                default:
+                    let u = options.readUnknownField;
+                    if (u === "throw")
+                        throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
+                    let d = reader.skip(wireType);
+                    if (u !== false)
+                        (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
+            }
+        }
+        return message;
+    }
+    internalBinaryWrite(message: GroupFolder, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
+        /* string folderId = 1; */
+        if (message.folderId !== "")
+            writer.tag(1, WireType.LengthDelimited).string(message.folderId);
+        /* string name = 2; */
+        if (message.name !== "")
+            writer.tag(2, WireType.LengthDelimited).string(message.name);
+        /* string creatorUin = 5; */
+        if (message.creatorUin !== "")
+            writer.tag(5, WireType.LengthDelimited).string(message.creatorUin);
+        /* uint32 createTime = 6; */
+        if (message.createTime !== 0)
+            writer.tag(6, WireType.Varint).uint32(message.createTime);
+        /* uint32 fileCount = 11; */
+        if (message.fileCount !== 0)
+            writer.tag(11, WireType.Varint).uint32(message.fileCount);
+        let u = options.writeUnknownFields;
+        if (u !== false)
+            (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
+        return writer;
+    }
+}
+/**
+ * @generated MessageType for protobuf message Laana.GroupFolder
+ */
+export const GroupFolder = new GroupFolder$Type();
diff --git a/src/laana-v0.1.3/types/entity/group.ts b/src/laana-v0.2.0/types/entity/group.ts
similarity index 100%
rename from src/laana-v0.1.3/types/entity/group.ts
rename to src/laana-v0.2.0/types/entity/group.ts
diff --git a/src/laana-v0.1.3/types/entity/message.ts b/src/laana-v0.2.0/types/entity/message.ts
similarity index 100%
rename from src/laana-v0.1.3/types/entity/message.ts
rename to src/laana-v0.2.0/types/entity/message.ts
diff --git a/src/laana-v0.1.3/types/entity/user.ts b/src/laana-v0.2.0/types/entity/user.ts
similarity index 100%
rename from src/laana-v0.1.3/types/entity/user.ts
rename to src/laana-v0.2.0/types/entity/user.ts
diff --git a/src/laana-v0.1.3/types/event/buddy.ts b/src/laana-v0.2.0/types/event/buddy.ts
similarity index 100%
rename from src/laana-v0.1.3/types/event/buddy.ts
rename to src/laana-v0.2.0/types/event/buddy.ts
diff --git a/src/laana-v0.1.3/types/event/group.ts b/src/laana-v0.2.0/types/event/group.ts
similarity index 100%
rename from src/laana-v0.1.3/types/event/group.ts
rename to src/laana-v0.2.0/types/event/group.ts
diff --git a/src/laana-v0.1.3/types/event/request.ts b/src/laana-v0.2.0/types/event/request.ts
similarity index 100%
rename from src/laana-v0.1.3/types/event/request.ts
rename to src/laana-v0.2.0/types/event/request.ts
diff --git a/src/laana-v0.1.3/types/event/wrapper.ts b/src/laana-v0.2.0/types/event/wrapper.ts
similarity index 85%
rename from src/laana-v0.1.3/types/event/wrapper.ts
rename to src/laana-v0.2.0/types/event/wrapper.ts
index 406766bd..a6df0823 100644
--- a/src/laana-v0.1.3/types/event/wrapper.ts
+++ b/src/laana-v0.2.0/types/event/wrapper.ts
@@ -148,10 +148,29 @@ export interface EventWrapper {
          * @generated from protobuf field: Laana.SelfInvitedToGroupEvent selfInvitedToGroupEvent = 303;
          */
         selfInvitedToGroupEvent: SelfInvitedToGroupEvent;
+    } | {
+        oneofKind: "extendedEvent";
+        /**
+         * @generated from protobuf field: Laana.ExtendedEvent extendedEvent = 9999;
+         */
+        extendedEvent: ExtendedEvent;
     } | {
         oneofKind: undefined;
     };
 }
+/**
+ * @generated from protobuf message Laana.ExtendedEvent
+ */
+export interface ExtendedEvent {
+    /**
+     * @generated from protobuf field: string eventName = 1;
+     */
+    eventName: string;
+    /**
+     * @generated from protobuf field: bytes eventData = 2;
+     */
+    eventData: Uint8Array;
+}
 // @generated message type with reflection information, may provide speed optimized methods
 class EventWrapper$Type extends MessageType<EventWrapper> {
     constructor() {
@@ -175,7 +194,8 @@ class EventWrapper$Type extends MessageType<EventWrapper> {
             { no: 212, name: "groupEmojiLikeEvent", kind: "message", oneof: "event", T: () => GroupEmojiLikeEvent },
             { no: 301, name: "someoneRequestToAddBuddyEvent", kind: "message", oneof: "event", T: () => SomeoneRequestToAddBuddyEvent },
             { no: 302, name: "someoneRequestToJoinGroupEvent", kind: "message", oneof: "event", T: () => SomeoneRequestToJoinGroupEvent },
-            { no: 303, name: "selfInvitedToGroupEvent", kind: "message", oneof: "event", T: () => SelfInvitedToGroupEvent }
+            { no: 303, name: "selfInvitedToGroupEvent", kind: "message", oneof: "event", T: () => SelfInvitedToGroupEvent },
+            { no: 9999, name: "extendedEvent", kind: "message", oneof: "event", T: () => ExtendedEvent }
         ]);
     }
     create(value?: PartialMessage<EventWrapper>): EventWrapper {
@@ -304,6 +324,12 @@ class EventWrapper$Type extends MessageType<EventWrapper> {
                         selfInvitedToGroupEvent: SelfInvitedToGroupEvent.internalBinaryRead(reader, reader.uint32(), options, (message.event as any).selfInvitedToGroupEvent)
                     };
                     break;
+                case /* Laana.ExtendedEvent extendedEvent */ 9999:
+                    message.event = {
+                        oneofKind: "extendedEvent",
+                        extendedEvent: ExtendedEvent.internalBinaryRead(reader, reader.uint32(), options, (message.event as any).extendedEvent)
+                    };
+                    break;
                 default:
                     let u = options.readUnknownField;
                     if (u === "throw")
@@ -376,6 +402,9 @@ class EventWrapper$Type extends MessageType<EventWrapper> {
         /* Laana.SelfInvitedToGroupEvent selfInvitedToGroupEvent = 303; */
         if (message.event.oneofKind === "selfInvitedToGroupEvent")
             SelfInvitedToGroupEvent.internalBinaryWrite(message.event.selfInvitedToGroupEvent, writer.tag(303, WireType.LengthDelimited).fork(), options).join();
+        /* Laana.ExtendedEvent extendedEvent = 9999; */
+        if (message.event.oneofKind === "extendedEvent")
+            ExtendedEvent.internalBinaryWrite(message.event.extendedEvent, writer.tag(9999, WireType.LengthDelimited).fork(), options).join();
         let u = options.writeUnknownFields;
         if (u !== false)
             (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
@@ -386,3 +415,58 @@ class EventWrapper$Type extends MessageType<EventWrapper> {
  * @generated MessageType for protobuf message Laana.EventWrapper
  */
 export const EventWrapper = new EventWrapper$Type();
+// @generated message type with reflection information, may provide speed optimized methods
+class ExtendedEvent$Type extends MessageType<ExtendedEvent> {
+    constructor() {
+        super("Laana.ExtendedEvent", [
+            { no: 1, name: "eventName", kind: "scalar", T: 9 /*ScalarType.STRING*/ },
+            { no: 2, name: "eventData", kind: "scalar", T: 12 /*ScalarType.BYTES*/ }
+        ]);
+    }
+    create(value?: PartialMessage<ExtendedEvent>): ExtendedEvent {
+        const message = globalThis.Object.create((this.messagePrototype!));
+        message.eventName = "";
+        message.eventData = new Uint8Array(0);
+        if (value !== undefined)
+            reflectionMergePartial<ExtendedEvent>(this, message, value);
+        return message;
+    }
+    internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: ExtendedEvent): ExtendedEvent {
+        let message = target ?? this.create(), end = reader.pos + length;
+        while (reader.pos < end) {
+            let [fieldNo, wireType] = reader.tag();
+            switch (fieldNo) {
+                case /* string eventName */ 1:
+                    message.eventName = reader.string();
+                    break;
+                case /* bytes eventData */ 2:
+                    message.eventData = reader.bytes();
+                    break;
+                default:
+                    let u = options.readUnknownField;
+                    if (u === "throw")
+                        throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
+                    let d = reader.skip(wireType);
+                    if (u !== false)
+                        (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
+            }
+        }
+        return message;
+    }
+    internalBinaryWrite(message: ExtendedEvent, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
+        /* string eventName = 1; */
+        if (message.eventName !== "")
+            writer.tag(1, WireType.LengthDelimited).string(message.eventName);
+        /* bytes eventData = 2; */
+        if (message.eventData.length)
+            writer.tag(2, WireType.LengthDelimited).bytes(message.eventData);
+        let u = options.writeUnknownFields;
+        if (u !== false)
+            (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
+        return writer;
+    }
+}
+/**
+ * @generated MessageType for protobuf message Laana.ExtendedEvent
+ */
+export const ExtendedEvent = new ExtendedEvent$Type();
diff --git a/src/laana-v0.1.3/types/laana.ts b/src/laana-v0.2.0/types/laana.ts
similarity index 54%
rename from src/laana-v0.1.3/types/laana.ts
rename to src/laana-v0.2.0/types/laana.ts
index cb48b938..0228f5f8 100644
--- a/src/laana-v0.1.3/types/laana.ts
+++ b/src/laana-v0.2.0/types/laana.ts
@@ -10,6 +10,7 @@ import { UnknownFieldHandler } from "@protobuf-ts/runtime";
 import type { PartialMessage } from "@protobuf-ts/runtime";
 import { reflectionMergePartial } from "@protobuf-ts/runtime";
 import { MessageType } from "@protobuf-ts/runtime";
+import { Message } from "./entity/message";
 import { EventWrapper } from "./event/wrapper";
 import { ActionPong } from "./action/wrapper";
 import { ActionPing } from "./action/wrapper";
@@ -38,17 +39,44 @@ export interface LaanaDataWrapper {
          * @generated from protobuf field: Laana.EventWrapper event = 3;
          */
         event: EventWrapper;
+    } | {
+        oneofKind: "message";
+        /**
+         * @generated from protobuf field: Laana.Message message = 4;
+         */
+        message: Message;
+    } | {
+        oneofKind: "extendedData";
+        /**
+         * @generated from protobuf field: Laana.ExtendedData extendedData = 99;
+         */
+        extendedData: ExtendedData;
     } | {
         oneofKind: undefined;
     };
 }
+/**
+ * @generated from protobuf message Laana.ExtendedData
+ */
+export interface ExtendedData {
+    /**
+     * @generated from protobuf field: string key = 1;
+     */
+    key: string;
+    /**
+     * @generated from protobuf field: bytes value = 2;
+     */
+    value: Uint8Array;
+}
 // @generated message type with reflection information, may provide speed optimized methods
 class LaanaDataWrapper$Type extends MessageType<LaanaDataWrapper> {
     constructor() {
         super("Laana.LaanaDataWrapper", [
             { no: 1, name: "actionPing", kind: "message", oneof: "data", T: () => ActionPing },
             { no: 2, name: "actionPong", kind: "message", oneof: "data", T: () => ActionPong },
-            { no: 3, name: "event", kind: "message", oneof: "data", T: () => EventWrapper }
+            { no: 3, name: "event", kind: "message", oneof: "data", T: () => EventWrapper },
+            { no: 4, name: "message", kind: "message", oneof: "data", T: () => Message },
+            { no: 99, name: "extendedData", kind: "message", oneof: "data", T: () => ExtendedData }
         ]);
     }
     create(value?: PartialMessage<LaanaDataWrapper>): LaanaDataWrapper {
@@ -81,6 +109,18 @@ class LaanaDataWrapper$Type extends MessageType<LaanaDataWrapper> {
                         event: EventWrapper.internalBinaryRead(reader, reader.uint32(), options, (message.data as any).event)
                     };
                     break;
+                case /* Laana.Message message */ 4:
+                    message.data = {
+                        oneofKind: "message",
+                        message: Message.internalBinaryRead(reader, reader.uint32(), options, (message.data as any).message)
+                    };
+                    break;
+                case /* Laana.ExtendedData extendedData */ 99:
+                    message.data = {
+                        oneofKind: "extendedData",
+                        extendedData: ExtendedData.internalBinaryRead(reader, reader.uint32(), options, (message.data as any).extendedData)
+                    };
+                    break;
                 default:
                     let u = options.readUnknownField;
                     if (u === "throw")
@@ -102,6 +142,12 @@ class LaanaDataWrapper$Type extends MessageType<LaanaDataWrapper> {
         /* Laana.EventWrapper event = 3; */
         if (message.data.oneofKind === "event")
             EventWrapper.internalBinaryWrite(message.data.event, writer.tag(3, WireType.LengthDelimited).fork(), options).join();
+        /* Laana.Message message = 4; */
+        if (message.data.oneofKind === "message")
+            Message.internalBinaryWrite(message.data.message, writer.tag(4, WireType.LengthDelimited).fork(), options).join();
+        /* Laana.ExtendedData extendedData = 99; */
+        if (message.data.oneofKind === "extendedData")
+            ExtendedData.internalBinaryWrite(message.data.extendedData, writer.tag(99, WireType.LengthDelimited).fork(), options).join();
         let u = options.writeUnknownFields;
         if (u !== false)
             (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
@@ -112,3 +158,58 @@ class LaanaDataWrapper$Type extends MessageType<LaanaDataWrapper> {
  * @generated MessageType for protobuf message Laana.LaanaDataWrapper
  */
 export const LaanaDataWrapper = new LaanaDataWrapper$Type();
+// @generated message type with reflection information, may provide speed optimized methods
+class ExtendedData$Type extends MessageType<ExtendedData> {
+    constructor() {
+        super("Laana.ExtendedData", [
+            { no: 1, name: "key", kind: "scalar", T: 9 /*ScalarType.STRING*/ },
+            { no: 2, name: "value", kind: "scalar", T: 12 /*ScalarType.BYTES*/ }
+        ]);
+    }
+    create(value?: PartialMessage<ExtendedData>): ExtendedData {
+        const message = globalThis.Object.create((this.messagePrototype!));
+        message.key = "";
+        message.value = new Uint8Array(0);
+        if (value !== undefined)
+            reflectionMergePartial<ExtendedData>(this, message, value);
+        return message;
+    }
+    internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: ExtendedData): ExtendedData {
+        let message = target ?? this.create(), end = reader.pos + length;
+        while (reader.pos < end) {
+            let [fieldNo, wireType] = reader.tag();
+            switch (fieldNo) {
+                case /* string key */ 1:
+                    message.key = reader.string();
+                    break;
+                case /* bytes value */ 2:
+                    message.value = reader.bytes();
+                    break;
+                default:
+                    let u = options.readUnknownField;
+                    if (u === "throw")
+                        throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
+                    let d = reader.skip(wireType);
+                    if (u !== false)
+                        (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
+            }
+        }
+        return message;
+    }
+    internalBinaryWrite(message: ExtendedData, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
+        /* string key = 1; */
+        if (message.key !== "")
+            writer.tag(1, WireType.LengthDelimited).string(message.key);
+        /* bytes value = 2; */
+        if (message.value.length)
+            writer.tag(2, WireType.LengthDelimited).bytes(message.value);
+        let u = options.writeUnknownFields;
+        if (u !== false)
+            (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
+        return writer;
+    }
+}
+/**
+ * @generated MessageType for protobuf message Laana.ExtendedData
+ */
+export const ExtendedData = new ExtendedData$Type();
diff --git a/src/laana-v0.1.3/utils/file.ts b/src/laana-v0.2.0/utils/file.ts
similarity index 95%
rename from src/laana-v0.1.3/utils/file.ts
rename to src/laana-v0.2.0/utils/file.ts
index 9dabc834..8ab77544 100644
--- a/src/laana-v0.1.3/utils/file.ts
+++ b/src/laana-v0.2.0/utils/file.ts
@@ -1,6 +1,6 @@
 import { NapCatCore } from '@/core';
 import { NapCatLaanaAdapter } from '..';
-import { File as LaanaFile } from '@/laana-v0.1.3/types/entity/file';
+import { File as LaanaFile } from '../types/entity/file';
 import path from 'path';
 import fs from 'fs';
 import fsPromises from 'fs/promises';
diff --git a/src/laana-v0.1.3/utils/message.ts b/src/laana-v0.2.0/utils/message.ts
similarity index 98%
rename from src/laana-v0.1.3/utils/message.ts
rename to src/laana-v0.2.0/utils/message.ts
index a448b3af..01f68c4d 100644
--- a/src/laana-v0.1.3/utils/message.ts
+++ b/src/laana-v0.2.0/utils/message.ts
@@ -1,7 +1,7 @@
 import { AtType, ChatType, ElementType, NapCatCore, Peer, SendMessageElement, SendTextElement } from '@/core';
 import { NapCatLaanaAdapter } from '..';
-import { OutgoingMessage, SendMessagePing } from '@/laana-v0.1.3/types/action/message';
-import { Peer as LaanaPeer, Peer_Type } from '@/laana-v0.1.3/types/entity/message';
+import { OutgoingMessage, SendMessagePing } from '../types/action/message';
+import { Peer as LaanaPeer, Peer_Type } from '../types/entity/message';
 import faceConfig from '@/core/external/face_config.json';
 
 type Laana2RawConverters = {