unplugin-devpilot 0.0.4 → 0.0.5

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 CHANGED
@@ -79,6 +79,7 @@ export default defineConfig({
79
79
  wsPort: 3100, // Optional: Specify WebSocket port (will be randomly allocated if not specified)
80
80
  mcpPort: 3101, // Optional: Specify MCP server port (will use random port if specified port is occupied)
81
81
  plugins: [], // Optional: Array of DevpilotPlugin instances
82
+ skillPaths: ['./.github/skills/devpilot', './.cursor/skills/devpilot'], // Optional: Array of paths to core skill files
82
83
  }),
83
84
  ],
84
85
  });
@@ -10,6 +10,12 @@ interface ClientInfo {
10
10
  interface BaseServerFunctions {
11
11
  ping: () => string;
12
12
  updateClientInfo: (info: Omit<ClientInfo, "clientId" | "connectedAt" | "lastActiveAt">) => void;
13
+ storageGetItem: (namespace: string, key: string) => Promise<any>;
14
+ storageSetItem: (namespace: string, key: string, value: any) => Promise<void>;
15
+ storageRemoveItem: (namespace: string, key: string) => Promise<void>;
16
+ storageGetKeys: (namespace: string, base?: string) => Promise<string[]>;
17
+ storageHasItem: (namespace: string, key: string) => Promise<boolean>;
18
+ storageClear: (namespace: string, base?: string) => Promise<void>;
13
19
  }
14
20
  interface PluginServerFunctions {}
15
21
  type ServerFunctions = BaseServerFunctions & PluginServerFunctions;
@@ -36,6 +42,17 @@ interface DevpilotClientOptions {
36
42
  extendRpcHandlers?: Record<string, (...args: any[]) => any>;
37
43
  }
38
44
  //#endregion
45
+ //#region src/client/storage.d.ts
46
+ interface ClientStorage {
47
+ getItem: <T = any>(key: string) => Promise<T | null>;
48
+ setItem: <T = any>(key: string, value: T) => Promise<void>;
49
+ removeItem: (key: string) => Promise<void>;
50
+ getKeys: (base?: string) => Promise<string[]>;
51
+ hasItem: (key: string) => Promise<boolean>;
52
+ clear: (base?: string) => Promise<void>;
53
+ }
54
+ declare function createClientStorage(client: DevpilotClient<any>, namespace: string): ClientStorage;
55
+ //#endregion
39
56
  //#region src/client/index.d.ts
40
57
  declare function createDevpilotClient<S extends Record<string, any> = ServerFunctions>(options: DevpilotClientOptions): DevpilotClient<S>;
41
58
  declare function initDevpilot<S extends Record<string, any> = ServerFunctions>(options: DevpilotClientOptions): DevpilotClient<S>;
@@ -59,4 +76,4 @@ declare function getDevpilotClient<S extends Record<string, any> = ServerFunctio
59
76
  */
60
77
  declare function defineRpcHandlers<T extends { [K in keyof T]: (...args: any[]) => any }>(handlers: T): T;
61
78
  //#endregion
62
- export { type DevpilotClient, type DevpilotClientOptions, type RpcHandlers, createDevpilotClient, defineRpcHandlers, getDevpilotClient, initDevpilot };
79
+ export { type ClientStorage, type DevpilotClient, type DevpilotClientOptions, type RpcHandlers, createClientStorage, createDevpilotClient, defineRpcHandlers, getDevpilotClient, initDevpilot };
@@ -1,3 +1,16 @@
1
+ //#region src/client/storage.ts
2
+ function createClientStorage(client, namespace) {
3
+ return {
4
+ getItem: (key) => client.rpcCall("storageGetItem", namespace, key),
5
+ setItem: (key, value) => client.rpcCall("storageSetItem", namespace, key, value),
6
+ removeItem: (key) => client.rpcCall("storageRemoveItem", namespace, key),
7
+ getKeys: (base) => client.rpcCall("storageGetKeys", namespace, base),
8
+ hasItem: (key) => client.rpcCall("storageHasItem", namespace, key),
9
+ clear: (base) => client.rpcCall("storageClear", namespace, base)
10
+ };
11
+ }
12
+
13
+ //#endregion
1
14
  //#region src/client/index.ts
2
15
  function generateId() {
3
16
  return Math.random().toString(36).slice(2, 12);
@@ -143,4 +156,4 @@ function defineRpcHandlers(handlers) {
143
156
  }
144
157
 
145
158
  //#endregion
146
- export { createDevpilotClient, defineRpcHandlers, getDevpilotClient, initDevpilot };
159
+ export { createClientStorage, createDevpilotClient, defineRpcHandlers, getDevpilotClient, initDevpilot };
package/dist/farm.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { t as unpluginDevpilot } from "./index-WH3owjvn.mjs";
1
+ import { t as unpluginDevpilot } from "./index-DMYihCqJ.mjs";
2
2
 
3
3
  //#region src/farm.d.ts
4
4
  /**
package/dist/farm.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { n as unpluginDevpilot } from "./src-AEXLBOF9.mjs";
1
+ import { n as unpluginDevpilot } from "./src-DkQU5cZx.mjs";
2
2
 
3
3
  //#region src/farm.ts
4
4
  /**
@@ -1,3 +1,124 @@
1
+ //#region ../../node_modules/.pnpm/unstorage@1.17.4/node_modules/unstorage/dist/shared/unstorage.Ca7R4QL2.d.mts
2
+ type StorageValue = null | string | number | boolean | object;
3
+ type WatchEvent = "update" | "remove";
4
+ type WatchCallback = (event: WatchEvent, key: string) => any;
5
+ type MaybePromise<T> = T | Promise<T>;
6
+ type MaybeDefined<T> = T extends any ? T : any;
7
+ type Unwatch = () => MaybePromise<void>;
8
+ interface StorageMeta {
9
+ atime?: Date;
10
+ mtime?: Date;
11
+ ttl?: number;
12
+ [key: string]: StorageValue | Date | undefined;
13
+ }
14
+ type TransactionOptions = Record<string, any>;
15
+ type GetKeysOptions = TransactionOptions & {
16
+ maxDepth?: number;
17
+ };
18
+ interface DriverFlags {
19
+ maxDepth?: boolean;
20
+ ttl?: boolean;
21
+ }
22
+ interface Driver<OptionsT = any, InstanceT = any> {
23
+ name?: string;
24
+ flags?: DriverFlags;
25
+ options?: OptionsT;
26
+ getInstance?: () => InstanceT;
27
+ hasItem: (key: string, opts: TransactionOptions) => MaybePromise<boolean>;
28
+ getItem: (key: string, opts?: TransactionOptions) => MaybePromise<StorageValue>;
29
+ /** @experimental */
30
+ getItems?: (items: {
31
+ key: string;
32
+ options?: TransactionOptions;
33
+ }[], commonOptions?: TransactionOptions) => MaybePromise<{
34
+ key: string;
35
+ value: StorageValue;
36
+ }[]>;
37
+ /** @experimental */
38
+ getItemRaw?: (key: string, opts: TransactionOptions) => MaybePromise<unknown>;
39
+ setItem?: (key: string, value: string, opts: TransactionOptions) => MaybePromise<void>;
40
+ /** @experimental */
41
+ setItems?: (items: {
42
+ key: string;
43
+ value: string;
44
+ options?: TransactionOptions;
45
+ }[], commonOptions?: TransactionOptions) => MaybePromise<void>;
46
+ /** @experimental */
47
+ setItemRaw?: (key: string, value: any, opts: TransactionOptions) => MaybePromise<void>;
48
+ removeItem?: (key: string, opts: TransactionOptions) => MaybePromise<void>;
49
+ getMeta?: (key: string, opts: TransactionOptions) => MaybePromise<StorageMeta | null>;
50
+ getKeys: (base: string, opts: GetKeysOptions) => MaybePromise<string[]>;
51
+ clear?: (base: string, opts: TransactionOptions) => MaybePromise<void>;
52
+ dispose?: () => MaybePromise<void>;
53
+ watch?: (callback: WatchCallback) => MaybePromise<Unwatch>;
54
+ }
55
+ type StorageDefinition = {
56
+ items: unknown;
57
+ [key: string]: unknown;
58
+ };
59
+ type StorageItemMap<T> = T extends StorageDefinition ? T["items"] : T;
60
+ type StorageItemType<T, K> = K extends keyof StorageItemMap<T> ? StorageItemMap<T>[K] : T extends StorageDefinition ? StorageValue : T;
61
+ interface Storage<T extends StorageValue = StorageValue> {
62
+ hasItem<U extends Extract<T, StorageDefinition>, K extends keyof StorageItemMap<U>>(key: K, opts?: TransactionOptions): Promise<boolean>;
63
+ hasItem(key: string, opts?: TransactionOptions): Promise<boolean>;
64
+ getItem<U extends Extract<T, StorageDefinition>, K extends string & keyof StorageItemMap<U>>(key: K, ops?: TransactionOptions): Promise<StorageItemType<T, K> | null>;
65
+ getItem<R = StorageItemType<T, string>>(key: string, opts?: TransactionOptions): Promise<R | null>;
66
+ /** @experimental */
67
+ getItems: <U extends T>(items: (string | {
68
+ key: string;
69
+ options?: TransactionOptions;
70
+ })[], commonOptions?: TransactionOptions) => Promise<{
71
+ key: string;
72
+ value: U;
73
+ }[]>;
74
+ /** @experimental See https://github.com/unjs/unstorage/issues/142 */
75
+ getItemRaw: <T = any>(key: string, opts?: TransactionOptions) => Promise<MaybeDefined<T> | null>;
76
+ setItem<U extends Extract<T, StorageDefinition>, K extends keyof StorageItemMap<U>>(key: K, value: StorageItemType<T, K>, opts?: TransactionOptions): Promise<void>;
77
+ setItem<U extends T>(key: string, value: U, opts?: TransactionOptions): Promise<void>;
78
+ /** @experimental */
79
+ setItems: <U extends T>(items: {
80
+ key: string;
81
+ value: U;
82
+ options?: TransactionOptions;
83
+ }[], commonOptions?: TransactionOptions) => Promise<void>;
84
+ /** @experimental See https://github.com/unjs/unstorage/issues/142 */
85
+ setItemRaw: <T = any>(key: string, value: MaybeDefined<T>, opts?: TransactionOptions) => Promise<void>;
86
+ removeItem<U extends Extract<T, StorageDefinition>, K extends keyof StorageItemMap<U>>(key: K, opts?: (TransactionOptions & {
87
+ removeMeta?: boolean;
88
+ }) | boolean): Promise<void>;
89
+ removeItem(key: string, opts?: (TransactionOptions & {
90
+ removeMeta?: boolean;
91
+ }) | boolean): Promise<void>;
92
+ getMeta: (key: string, opts?: (TransactionOptions & {
93
+ nativeOnly?: boolean;
94
+ }) | boolean) => MaybePromise<StorageMeta>;
95
+ setMeta: (key: string, value: StorageMeta, opts?: TransactionOptions) => Promise<void>;
96
+ removeMeta: (key: string, opts?: TransactionOptions) => Promise<void>;
97
+ getKeys: (base?: string, opts?: GetKeysOptions) => Promise<string[]>;
98
+ clear: (base?: string, opts?: TransactionOptions) => Promise<void>;
99
+ dispose: () => Promise<void>;
100
+ watch: (callback: WatchCallback) => Promise<Unwatch>;
101
+ unwatch: () => Promise<void>;
102
+ mount: (base: string, driver: Driver) => Storage;
103
+ unmount: (base: string, dispose?: boolean) => Promise<void>;
104
+ getMount: (key?: string) => {
105
+ base: string;
106
+ driver: Driver;
107
+ };
108
+ getMounts: (base?: string, options?: {
109
+ parents?: boolean;
110
+ }) => {
111
+ base: string;
112
+ driver: Driver;
113
+ }[];
114
+ keys: Storage["getKeys"];
115
+ get: Storage<T>["getItem"];
116
+ set: Storage<T>["setItem"];
117
+ has: Storage<T>["hasItem"];
118
+ del: Storage<T>["removeItem"];
119
+ remove: Storage<T>["removeItem"];
120
+ }
121
+ //#endregion
1
122
  //#region src/core/utils.d.ts
2
123
  /**
3
124
  * Resolve the module path relative to the plugin to an absolute path
@@ -4123,6 +4244,7 @@ declare function defineMcpToolRegister<OutputArgs extends ZodRawShapeCompat | An
4123
4244
  //#region src/core/plugin/index.d.ts
4124
4245
  interface DevpilotPluginContext {
4125
4246
  wsPort: number;
4247
+ storage: Storage;
4126
4248
  }
4127
4249
  /**
4128
4250
  * Resolve the module path relative to the plugin to an absolute path
@@ -4143,4 +4265,4 @@ interface DevpilotPluginContext {
4143
4265
  */
4144
4266
  declare function resolveClientModule(importMetaUrl: string, relativePath: string): string;
4145
4267
  //#endregion
4146
- export { resolveModule as a, defineMcpToolRegister as i, resolveClientModule as n, McpToolRegister as r, DevpilotPluginContext as t };
4268
+ export { type resolveModule as a, defineMcpToolRegister as i, resolveClientModule as n, Storage as o, McpToolRegister as r, StorageValue as s, DevpilotPluginContext as t };
@@ -1,4 +1,4 @@
1
- import { r as McpToolRegister, t as DevpilotPluginContext } from "./index-Csy16I0Z.mjs";
1
+ import { o as Storage, r as McpToolRegister, s as StorageValue, t as DevpilotPluginContext } from "./index-B3RgT4Na.mjs";
2
2
  import { UnpluginInstance } from "unplugin";
3
3
  import { WebSocket } from "ws";
4
4
 
@@ -45,20 +45,20 @@ interface Options {
45
45
  mcpPort?: number;
46
46
  plugins?: DevpilotPlugin[];
47
47
  /**
48
- * The path to generate the core skill file
49
- * - directory path: './src/skills/devpilot' (will generate SKILL.md in this directory)
50
- * - file path: './src/skills/devpilot/SKILL.md' (will generate the specified file)
48
+ * The paths to generate the core skill files
49
+ * - directory path: './.github/skills/devpilot' (will generate SKILL.md in this directory)
50
+ * - file path: './.github/skills/devpilot/SKILL.md' (will generate the specified file)
51
51
  *
52
52
  * If not specified, no core skill file will be generated
53
53
  * @example
54
54
  * ```ts
55
55
  * Devpilot({
56
- * skillCorePath: './src/skills/devpilot',
56
+ * skillPaths: ['./.github/skills/devpilot', './.cursor/skills/devpilot'],
57
57
  * plugins: [],
58
58
  * })
59
59
  * ```
60
60
  */
61
- skillCorePath?: string;
61
+ skillPaths?: string[];
62
62
  }
63
63
  //#endregion
64
64
  //#region ../../node_modules/.pnpm/birpc@4.0.0/node_modules/birpc/dist/index.d.mts
@@ -188,6 +188,12 @@ interface PendingTask {
188
188
  interface BaseServerFunctions {
189
189
  ping: () => string;
190
190
  updateClientInfo: (info: Omit<ClientInfo, "clientId" | "connectedAt" | "lastActiveAt">) => void;
191
+ storageGetItem: (namespace: string, key: string) => Promise<any>;
192
+ storageSetItem: (namespace: string, key: string, value: any) => Promise<void>;
193
+ storageRemoveItem: (namespace: string, key: string) => Promise<void>;
194
+ storageGetKeys: (namespace: string, base?: string) => Promise<string[]>;
195
+ storageHasItem: (namespace: string, key: string) => Promise<boolean>;
196
+ storageClear: (namespace: string, base?: string) => Promise<void>;
191
197
  }
192
198
  interface PluginServerFunctions {}
193
199
  type ServerFunctions = BaseServerFunctions & PluginServerFunctions;
@@ -271,7 +277,11 @@ declare const clientManager: ClientManager;
271
277
  */
272
278
  declare function resolveSkillModule(importMetaUrl: string, relativePath: string): string;
273
279
  //#endregion
280
+ //#region src/core/storage.d.ts
281
+ declare const storage: Storage<StorageValue>;
282
+ declare function getPluginStorage(namespace: string): Storage<StorageValue>;
283
+ //#endregion
274
284
  //#region src/index.d.ts
275
285
  declare const unpluginDevpilot: UnpluginInstance<Options | undefined, false>;
276
286
  //#endregion
277
- export { BaseServerFunctions as a, ClientInfo as c, PluginServerFunctions as d, ServerFunctions as f, Options as h, BaseClientFunctions as i, PendingTask as l, DevpilotPlugin as m, resolveSkillModule as n, ClientDiscoveryFilter as o, TaskHistory as p, clientManager as r, ClientFunctions as s, unpluginDevpilot as t, PluginClientFunctions as u };
287
+ export { Options as _, clientManager as a, ClientDiscoveryFilter as c, PendingTask as d, PluginClientFunctions as f, DevpilotPlugin as g, TaskHistory as h, resolveSkillModule as i, ClientFunctions as l, ServerFunctions as m, getPluginStorage as n, BaseClientFunctions as o, PluginServerFunctions as p, storage as r, BaseServerFunctions as s, unpluginDevpilot as t, ClientInfo as u };
package/dist/index.d.mts CHANGED
@@ -1,3 +1,3 @@
1
- import { a as resolveModule, i as defineMcpToolRegister, n as resolveClientModule, t as DevpilotPluginContext } from "./index-Csy16I0Z.mjs";
2
- import { a as BaseServerFunctions, c as ClientInfo, d as PluginServerFunctions, f as ServerFunctions, h as Options, i as BaseClientFunctions, l as PendingTask, m as DevpilotPlugin, n as resolveSkillModule, o as ClientDiscoveryFilter, p as TaskHistory, r as clientManager, s as ClientFunctions, t as unpluginDevpilot, u as PluginClientFunctions } from "./index-WH3owjvn.mjs";
3
- export { BaseClientFunctions, BaseServerFunctions, ClientDiscoveryFilter, ClientFunctions, ClientInfo, DevpilotPlugin, DevpilotPluginContext, Options, PendingTask, PluginClientFunctions, PluginServerFunctions, ServerFunctions, TaskHistory, clientManager, unpluginDevpilot as default, unpluginDevpilot, defineMcpToolRegister, resolveClientModule, resolveModule, resolveSkillModule };
1
+ import { a as resolveModule, i as defineMcpToolRegister, n as resolveClientModule, t as DevpilotPluginContext } from "./index-B3RgT4Na.mjs";
2
+ import { _ as Options, a as clientManager, c as ClientDiscoveryFilter, d as PendingTask, f as PluginClientFunctions, g as DevpilotPlugin, h as TaskHistory, i as resolveSkillModule, l as ClientFunctions, m as ServerFunctions, n as getPluginStorage, o as BaseClientFunctions, p as PluginServerFunctions, r as storage, s as BaseServerFunctions, t as unpluginDevpilot, u as ClientInfo } from "./index-DMYihCqJ.mjs";
3
+ export { BaseClientFunctions, BaseServerFunctions, ClientDiscoveryFilter, ClientFunctions, ClientInfo, DevpilotPlugin, DevpilotPluginContext, Options, PendingTask, PluginClientFunctions, PluginServerFunctions, ServerFunctions, TaskHistory, clientManager, unpluginDevpilot as default, unpluginDevpilot, defineMcpToolRegister, getPluginStorage, resolveClientModule, resolveModule, resolveSkillModule, storage };
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { i as clientManager, n as unpluginDevpilot, r as resolveSkillModule, t as src_default } from "./src-AEXLBOF9.mjs";
1
+ import { a as storage, i as getPluginStorage, n as unpluginDevpilot, o as clientManager, r as resolveSkillModule, t as src_default } from "./src-DkQU5cZx.mjs";
2
2
  import { n as defineMcpToolRegister, r as resolveModule, t as resolveClientModule } from "./plugin-B1Afr0m3.mjs";
3
3
 
4
- export { clientManager, src_default as default, defineMcpToolRegister, resolveClientModule, resolveModule, resolveSkillModule, unpluginDevpilot };
4
+ export { clientManager, src_default as default, defineMcpToolRegister, getPluginStorage, resolveClientModule, resolveModule, resolveSkillModule, storage, unpluginDevpilot };
package/dist/plugin.d.mts CHANGED
@@ -1,2 +1,2 @@
1
- import { a as resolveModule, i as defineMcpToolRegister, n as resolveClientModule, r as McpToolRegister, t as DevpilotPluginContext } from "./index-Csy16I0Z.mjs";
1
+ import { a as resolveModule, i as defineMcpToolRegister, n as resolveClientModule, r as McpToolRegister, t as DevpilotPluginContext } from "./index-B3RgT4Na.mjs";
2
2
  export { DevpilotPluginContext, McpToolRegister as McpServerRegister, defineMcpToolRegister, resolveClientModule, resolveModule };
package/dist/rspack.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { t as unpluginDevpilot } from "./index-WH3owjvn.mjs";
1
+ import { t as unpluginDevpilot } from "./index-DMYihCqJ.mjs";
2
2
 
3
3
  //#region src/rspack.d.ts
4
4
  /**
package/dist/rspack.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { n as unpluginDevpilot } from "./src-AEXLBOF9.mjs";
1
+ import { n as unpluginDevpilot } from "./src-DkQU5cZx.mjs";
2
2
 
3
3
  //#region src/rspack.ts
4
4
  /**
@@ -19799,7 +19799,7 @@ var StreamableHTTPServerTransport = class {
19799
19799
 
19800
19800
  //#endregion
19801
19801
  //#region package.json
19802
- var version = "0.0.4";
19802
+ var version = "0.0.5";
19803
19803
 
19804
19804
  //#endregion
19805
19805
  //#region ../../node_modules/.pnpm/es-toolkit@1.44.0/node_modules/es-toolkit/dist/compat/util/uniqueId.mjs
@@ -19960,6 +19960,486 @@ var ClientManager = class {
19960
19960
  };
19961
19961
  const clientManager = new ClientManager();
19962
19962
 
19963
+ //#endregion
19964
+ //#region ../../node_modules/.pnpm/destr@2.0.5/node_modules/destr/dist/index.mjs
19965
+ const suspectProtoRx = /"(?:_|\\u0{2}5[Ff]){2}(?:p|\\u0{2}70)(?:r|\\u0{2}72)(?:o|\\u0{2}6[Ff])(?:t|\\u0{2}74)(?:o|\\u0{2}6[Ff])(?:_|\\u0{2}5[Ff]){2}"\s*:/;
19966
+ const suspectConstructorRx = /"(?:c|\\u0063)(?:o|\\u006[Ff])(?:n|\\u006[Ee])(?:s|\\u0073)(?:t|\\u0074)(?:r|\\u0072)(?:u|\\u0075)(?:c|\\u0063)(?:t|\\u0074)(?:o|\\u006[Ff])(?:r|\\u0072)"\s*:/;
19967
+ const JsonSigRx = /^\s*["[{]|^\s*-?\d{1,16}(\.\d{1,17})?([Ee][+-]?\d+)?\s*$/;
19968
+ function jsonParseTransform(key, value) {
19969
+ if (key === "__proto__" || key === "constructor" && value && typeof value === "object" && "prototype" in value) {
19970
+ warnKeyDropped(key);
19971
+ return;
19972
+ }
19973
+ return value;
19974
+ }
19975
+ function warnKeyDropped(key) {
19976
+ console.warn(`[destr] Dropping "${key}" key to prevent prototype pollution.`);
19977
+ }
19978
+ function destr(value, options = {}) {
19979
+ if (typeof value !== "string") return value;
19980
+ if (value[0] === "\"" && value[value.length - 1] === "\"" && value.indexOf("\\") === -1) return value.slice(1, -1);
19981
+ const _value = value.trim();
19982
+ if (_value.length <= 9) switch (_value.toLowerCase()) {
19983
+ case "true": return true;
19984
+ case "false": return false;
19985
+ case "undefined": return;
19986
+ case "null": return null;
19987
+ case "nan": return NaN;
19988
+ case "infinity": return Number.POSITIVE_INFINITY;
19989
+ case "-infinity": return Number.NEGATIVE_INFINITY;
19990
+ }
19991
+ if (!JsonSigRx.test(value)) {
19992
+ if (options.strict) throw new SyntaxError("[destr] Invalid JSON");
19993
+ return value;
19994
+ }
19995
+ try {
19996
+ if (suspectProtoRx.test(value) || suspectConstructorRx.test(value)) {
19997
+ if (options.strict) throw new Error("[destr] Possible prototype pollution");
19998
+ return JSON.parse(value, jsonParseTransform);
19999
+ }
20000
+ return JSON.parse(value);
20001
+ } catch (error) {
20002
+ if (options.strict) throw error;
20003
+ return value;
20004
+ }
20005
+ }
20006
+
20007
+ //#endregion
20008
+ //#region ../../node_modules/.pnpm/unstorage@1.17.4/node_modules/unstorage/dist/shared/unstorage.zVDD2mZo.mjs
20009
+ function wrapToPromise(value) {
20010
+ if (!value || typeof value.then !== "function") return Promise.resolve(value);
20011
+ return value;
20012
+ }
20013
+ function asyncCall(function_, ...arguments_) {
20014
+ try {
20015
+ return wrapToPromise(function_(...arguments_));
20016
+ } catch (error) {
20017
+ return Promise.reject(error);
20018
+ }
20019
+ }
20020
+ function isPrimitive(value) {
20021
+ const type = typeof value;
20022
+ return value === null || type !== "object" && type !== "function";
20023
+ }
20024
+ function isPureObject(value) {
20025
+ const proto = Object.getPrototypeOf(value);
20026
+ return !proto || proto.isPrototypeOf(Object);
20027
+ }
20028
+ function stringify(value) {
20029
+ if (isPrimitive(value)) return String(value);
20030
+ if (isPureObject(value) || Array.isArray(value)) return JSON.stringify(value);
20031
+ if (typeof value.toJSON === "function") return stringify(value.toJSON());
20032
+ throw new Error("[unstorage] Cannot stringify value!");
20033
+ }
20034
+ const BASE64_PREFIX = "base64:";
20035
+ function serializeRaw(value) {
20036
+ if (typeof value === "string") return value;
20037
+ return BASE64_PREFIX + base64Encode(value);
20038
+ }
20039
+ function deserializeRaw(value) {
20040
+ if (typeof value !== "string") return value;
20041
+ if (!value.startsWith(BASE64_PREFIX)) return value;
20042
+ return base64Decode(value.slice(7));
20043
+ }
20044
+ function base64Decode(input) {
20045
+ if (globalThis.Buffer) return Buffer.from(input, "base64");
20046
+ return Uint8Array.from(globalThis.atob(input), (c) => c.codePointAt(0));
20047
+ }
20048
+ function base64Encode(input) {
20049
+ if (globalThis.Buffer) return Buffer.from(input).toString("base64");
20050
+ return globalThis.btoa(String.fromCodePoint(...input));
20051
+ }
20052
+ const storageKeyProperties = [
20053
+ "has",
20054
+ "hasItem",
20055
+ "get",
20056
+ "getItem",
20057
+ "getItemRaw",
20058
+ "set",
20059
+ "setItem",
20060
+ "setItemRaw",
20061
+ "del",
20062
+ "remove",
20063
+ "removeItem",
20064
+ "getMeta",
20065
+ "setMeta",
20066
+ "removeMeta",
20067
+ "getKeys",
20068
+ "clear",
20069
+ "mount",
20070
+ "unmount"
20071
+ ];
20072
+ function prefixStorage(storage, base) {
20073
+ base = normalizeBaseKey(base);
20074
+ if (!base) return storage;
20075
+ const nsStorage = { ...storage };
20076
+ for (const property of storageKeyProperties) nsStorage[property] = (key = "", ...args) => storage[property](base + key, ...args);
20077
+ nsStorage.getKeys = (key = "", ...arguments_) => storage.getKeys(base + key, ...arguments_).then((keys) => keys.map((key2) => key2.slice(base.length)));
20078
+ nsStorage.keys = nsStorage.getKeys;
20079
+ nsStorage.getItems = async (items, commonOptions) => {
20080
+ const prefixedItems = items.map((item) => typeof item === "string" ? base + item : {
20081
+ ...item,
20082
+ key: base + item.key
20083
+ });
20084
+ return (await storage.getItems(prefixedItems, commonOptions)).map((entry) => ({
20085
+ key: entry.key.slice(base.length),
20086
+ value: entry.value
20087
+ }));
20088
+ };
20089
+ nsStorage.setItems = async (items, commonOptions) => {
20090
+ const prefixedItems = items.map((item) => ({
20091
+ key: base + item.key,
20092
+ value: item.value,
20093
+ options: item.options
20094
+ }));
20095
+ return storage.setItems(prefixedItems, commonOptions);
20096
+ };
20097
+ return nsStorage;
20098
+ }
20099
+ function normalizeKey(key) {
20100
+ if (!key) return "";
20101
+ return key.split("?")[0]?.replace(/[/\\]/g, ":").replace(/:+/g, ":").replace(/^:|:$/g, "") || "";
20102
+ }
20103
+ function joinKeys(...keys) {
20104
+ return normalizeKey(keys.join(":"));
20105
+ }
20106
+ function normalizeBaseKey(base) {
20107
+ base = normalizeKey(base);
20108
+ return base ? base + ":" : "";
20109
+ }
20110
+ function filterKeyByDepth(key, depth) {
20111
+ if (depth === void 0) return true;
20112
+ let substrCount = 0;
20113
+ let index = key.indexOf(":");
20114
+ while (index > -1) {
20115
+ substrCount++;
20116
+ index = key.indexOf(":", index + 1);
20117
+ }
20118
+ return substrCount <= depth;
20119
+ }
20120
+ function filterKeyByBase(key, base) {
20121
+ if (base) return key.startsWith(base) && key[key.length - 1] !== "$";
20122
+ return key[key.length - 1] !== "$";
20123
+ }
20124
+
20125
+ //#endregion
20126
+ //#region ../../node_modules/.pnpm/unstorage@1.17.4/node_modules/unstorage/dist/index.mjs
20127
+ function defineDriver(factory) {
20128
+ return factory;
20129
+ }
20130
+ const DRIVER_NAME = "memory";
20131
+ const memory = defineDriver(() => {
20132
+ const data = /* @__PURE__ */ new Map();
20133
+ return {
20134
+ name: DRIVER_NAME,
20135
+ getInstance: () => data,
20136
+ hasItem(key) {
20137
+ return data.has(key);
20138
+ },
20139
+ getItem(key) {
20140
+ return data.get(key) ?? null;
20141
+ },
20142
+ getItemRaw(key) {
20143
+ return data.get(key) ?? null;
20144
+ },
20145
+ setItem(key, value) {
20146
+ data.set(key, value);
20147
+ },
20148
+ setItemRaw(key, value) {
20149
+ data.set(key, value);
20150
+ },
20151
+ removeItem(key) {
20152
+ data.delete(key);
20153
+ },
20154
+ getKeys() {
20155
+ return [...data.keys()];
20156
+ },
20157
+ clear() {
20158
+ data.clear();
20159
+ },
20160
+ dispose() {
20161
+ data.clear();
20162
+ }
20163
+ };
20164
+ });
20165
+ function createStorage(options = {}) {
20166
+ const context = {
20167
+ mounts: { "": options.driver || memory() },
20168
+ mountpoints: [""],
20169
+ watching: false,
20170
+ watchListeners: [],
20171
+ unwatch: {}
20172
+ };
20173
+ const getMount = (key) => {
20174
+ for (const base of context.mountpoints) if (key.startsWith(base)) return {
20175
+ base,
20176
+ relativeKey: key.slice(base.length),
20177
+ driver: context.mounts[base]
20178
+ };
20179
+ return {
20180
+ base: "",
20181
+ relativeKey: key,
20182
+ driver: context.mounts[""]
20183
+ };
20184
+ };
20185
+ const getMounts = (base, includeParent) => {
20186
+ return context.mountpoints.filter((mountpoint) => mountpoint.startsWith(base) || includeParent && base.startsWith(mountpoint)).map((mountpoint) => ({
20187
+ relativeBase: base.length > mountpoint.length ? base.slice(mountpoint.length) : void 0,
20188
+ mountpoint,
20189
+ driver: context.mounts[mountpoint]
20190
+ }));
20191
+ };
20192
+ const onChange = (event, key) => {
20193
+ if (!context.watching) return;
20194
+ key = normalizeKey(key);
20195
+ for (const listener of context.watchListeners) listener(event, key);
20196
+ };
20197
+ const startWatch = async () => {
20198
+ if (context.watching) return;
20199
+ context.watching = true;
20200
+ for (const mountpoint in context.mounts) context.unwatch[mountpoint] = await watch(context.mounts[mountpoint], onChange, mountpoint);
20201
+ };
20202
+ const stopWatch = async () => {
20203
+ if (!context.watching) return;
20204
+ for (const mountpoint in context.unwatch) await context.unwatch[mountpoint]();
20205
+ context.unwatch = {};
20206
+ context.watching = false;
20207
+ };
20208
+ const runBatch = (items, commonOptions, cb) => {
20209
+ const batches = /* @__PURE__ */ new Map();
20210
+ const getBatch = (mount) => {
20211
+ let batch = batches.get(mount.base);
20212
+ if (!batch) {
20213
+ batch = {
20214
+ driver: mount.driver,
20215
+ base: mount.base,
20216
+ items: []
20217
+ };
20218
+ batches.set(mount.base, batch);
20219
+ }
20220
+ return batch;
20221
+ };
20222
+ for (const item of items) {
20223
+ const isStringItem = typeof item === "string";
20224
+ const key = normalizeKey(isStringItem ? item : item.key);
20225
+ const value = isStringItem ? void 0 : item.value;
20226
+ const options2 = isStringItem || !item.options ? commonOptions : {
20227
+ ...commonOptions,
20228
+ ...item.options
20229
+ };
20230
+ const mount = getMount(key);
20231
+ getBatch(mount).items.push({
20232
+ key,
20233
+ value,
20234
+ relativeKey: mount.relativeKey,
20235
+ options: options2
20236
+ });
20237
+ }
20238
+ return Promise.all([...batches.values()].map((batch) => cb(batch))).then((r) => r.flat());
20239
+ };
20240
+ const storage = {
20241
+ hasItem(key, opts = {}) {
20242
+ key = normalizeKey(key);
20243
+ const { relativeKey, driver } = getMount(key);
20244
+ return asyncCall(driver.hasItem, relativeKey, opts);
20245
+ },
20246
+ getItem(key, opts = {}) {
20247
+ key = normalizeKey(key);
20248
+ const { relativeKey, driver } = getMount(key);
20249
+ return asyncCall(driver.getItem, relativeKey, opts).then((value) => destr(value));
20250
+ },
20251
+ getItems(items, commonOptions = {}) {
20252
+ return runBatch(items, commonOptions, (batch) => {
20253
+ if (batch.driver.getItems) return asyncCall(batch.driver.getItems, batch.items.map((item) => ({
20254
+ key: item.relativeKey,
20255
+ options: item.options
20256
+ })), commonOptions).then((r) => r.map((item) => ({
20257
+ key: joinKeys(batch.base, item.key),
20258
+ value: destr(item.value)
20259
+ })));
20260
+ return Promise.all(batch.items.map((item) => {
20261
+ return asyncCall(batch.driver.getItem, item.relativeKey, item.options).then((value) => ({
20262
+ key: item.key,
20263
+ value: destr(value)
20264
+ }));
20265
+ }));
20266
+ });
20267
+ },
20268
+ getItemRaw(key, opts = {}) {
20269
+ key = normalizeKey(key);
20270
+ const { relativeKey, driver } = getMount(key);
20271
+ if (driver.getItemRaw) return asyncCall(driver.getItemRaw, relativeKey, opts);
20272
+ return asyncCall(driver.getItem, relativeKey, opts).then((value) => deserializeRaw(value));
20273
+ },
20274
+ async setItem(key, value, opts = {}) {
20275
+ if (value === void 0) return storage.removeItem(key);
20276
+ key = normalizeKey(key);
20277
+ const { relativeKey, driver } = getMount(key);
20278
+ if (!driver.setItem) return;
20279
+ await asyncCall(driver.setItem, relativeKey, stringify(value), opts);
20280
+ if (!driver.watch) onChange("update", key);
20281
+ },
20282
+ async setItems(items, commonOptions) {
20283
+ await runBatch(items, commonOptions, async (batch) => {
20284
+ if (batch.driver.setItems) return asyncCall(batch.driver.setItems, batch.items.map((item) => ({
20285
+ key: item.relativeKey,
20286
+ value: stringify(item.value),
20287
+ options: item.options
20288
+ })), commonOptions);
20289
+ if (!batch.driver.setItem) return;
20290
+ await Promise.all(batch.items.map((item) => {
20291
+ return asyncCall(batch.driver.setItem, item.relativeKey, stringify(item.value), item.options);
20292
+ }));
20293
+ });
20294
+ },
20295
+ async setItemRaw(key, value, opts = {}) {
20296
+ if (value === void 0) return storage.removeItem(key, opts);
20297
+ key = normalizeKey(key);
20298
+ const { relativeKey, driver } = getMount(key);
20299
+ if (driver.setItemRaw) await asyncCall(driver.setItemRaw, relativeKey, value, opts);
20300
+ else if (driver.setItem) await asyncCall(driver.setItem, relativeKey, serializeRaw(value), opts);
20301
+ else return;
20302
+ if (!driver.watch) onChange("update", key);
20303
+ },
20304
+ async removeItem(key, opts = {}) {
20305
+ if (typeof opts === "boolean") opts = { removeMeta: opts };
20306
+ key = normalizeKey(key);
20307
+ const { relativeKey, driver } = getMount(key);
20308
+ if (!driver.removeItem) return;
20309
+ await asyncCall(driver.removeItem, relativeKey, opts);
20310
+ if (opts.removeMeta || opts.removeMata) await asyncCall(driver.removeItem, relativeKey + "$", opts);
20311
+ if (!driver.watch) onChange("remove", key);
20312
+ },
20313
+ async getMeta(key, opts = {}) {
20314
+ if (typeof opts === "boolean") opts = { nativeOnly: opts };
20315
+ key = normalizeKey(key);
20316
+ const { relativeKey, driver } = getMount(key);
20317
+ const meta = /* @__PURE__ */ Object.create(null);
20318
+ if (driver.getMeta) Object.assign(meta, await asyncCall(driver.getMeta, relativeKey, opts));
20319
+ if (!opts.nativeOnly) {
20320
+ const value = await asyncCall(driver.getItem, relativeKey + "$", opts).then((value_) => destr(value_));
20321
+ if (value && typeof value === "object") {
20322
+ if (typeof value.atime === "string") value.atime = new Date(value.atime);
20323
+ if (typeof value.mtime === "string") value.mtime = new Date(value.mtime);
20324
+ Object.assign(meta, value);
20325
+ }
20326
+ }
20327
+ return meta;
20328
+ },
20329
+ setMeta(key, value, opts = {}) {
20330
+ return this.setItem(key + "$", value, opts);
20331
+ },
20332
+ removeMeta(key, opts = {}) {
20333
+ return this.removeItem(key + "$", opts);
20334
+ },
20335
+ async getKeys(base, opts = {}) {
20336
+ base = normalizeBaseKey(base);
20337
+ const mounts = getMounts(base, true);
20338
+ let maskedMounts = [];
20339
+ const allKeys = [];
20340
+ let allMountsSupportMaxDepth = true;
20341
+ for (const mount of mounts) {
20342
+ if (!mount.driver.flags?.maxDepth) allMountsSupportMaxDepth = false;
20343
+ const rawKeys = await asyncCall(mount.driver.getKeys, mount.relativeBase, opts);
20344
+ for (const key of rawKeys) {
20345
+ const fullKey = mount.mountpoint + normalizeKey(key);
20346
+ if (!maskedMounts.some((p) => fullKey.startsWith(p))) allKeys.push(fullKey);
20347
+ }
20348
+ maskedMounts = [mount.mountpoint, ...maskedMounts.filter((p) => !p.startsWith(mount.mountpoint))];
20349
+ }
20350
+ const shouldFilterByDepth = opts.maxDepth !== void 0 && !allMountsSupportMaxDepth;
20351
+ return allKeys.filter((key) => (!shouldFilterByDepth || filterKeyByDepth(key, opts.maxDepth)) && filterKeyByBase(key, base));
20352
+ },
20353
+ async clear(base, opts = {}) {
20354
+ base = normalizeBaseKey(base);
20355
+ await Promise.all(getMounts(base, false).map(async (m) => {
20356
+ if (m.driver.clear) return asyncCall(m.driver.clear, m.relativeBase, opts);
20357
+ if (m.driver.removeItem) {
20358
+ const keys = await m.driver.getKeys(m.relativeBase || "", opts);
20359
+ return Promise.all(keys.map((key) => m.driver.removeItem(key, opts)));
20360
+ }
20361
+ }));
20362
+ },
20363
+ async dispose() {
20364
+ await Promise.all(Object.values(context.mounts).map((driver) => dispose(driver)));
20365
+ },
20366
+ async watch(callback) {
20367
+ await startWatch();
20368
+ context.watchListeners.push(callback);
20369
+ return async () => {
20370
+ context.watchListeners = context.watchListeners.filter((listener) => listener !== callback);
20371
+ if (context.watchListeners.length === 0) await stopWatch();
20372
+ };
20373
+ },
20374
+ async unwatch() {
20375
+ context.watchListeners = [];
20376
+ await stopWatch();
20377
+ },
20378
+ mount(base, driver) {
20379
+ base = normalizeBaseKey(base);
20380
+ if (base && context.mounts[base]) throw new Error(`already mounted at ${base}`);
20381
+ if (base) {
20382
+ context.mountpoints.push(base);
20383
+ context.mountpoints.sort((a, b) => b.length - a.length);
20384
+ }
20385
+ context.mounts[base] = driver;
20386
+ if (context.watching) Promise.resolve(watch(driver, onChange, base)).then((unwatcher) => {
20387
+ context.unwatch[base] = unwatcher;
20388
+ }).catch(console.error);
20389
+ return storage;
20390
+ },
20391
+ async unmount(base, _dispose = true) {
20392
+ base = normalizeBaseKey(base);
20393
+ if (!base || !context.mounts[base]) return;
20394
+ if (context.watching && base in context.unwatch) {
20395
+ context.unwatch[base]?.();
20396
+ delete context.unwatch[base];
20397
+ }
20398
+ if (_dispose) await dispose(context.mounts[base]);
20399
+ context.mountpoints = context.mountpoints.filter((key) => key !== base);
20400
+ delete context.mounts[base];
20401
+ },
20402
+ getMount(key = "") {
20403
+ key = normalizeKey(key) + ":";
20404
+ const m = getMount(key);
20405
+ return {
20406
+ driver: m.driver,
20407
+ base: m.base
20408
+ };
20409
+ },
20410
+ getMounts(base = "", opts = {}) {
20411
+ base = normalizeKey(base);
20412
+ return getMounts(base, opts.parents).map((m) => ({
20413
+ driver: m.driver,
20414
+ base: m.mountpoint
20415
+ }));
20416
+ },
20417
+ keys: (base, opts = {}) => storage.getKeys(base, opts),
20418
+ get: (key, opts = {}) => storage.getItem(key, opts),
20419
+ set: (key, value, opts = {}) => storage.setItem(key, value, opts),
20420
+ has: (key, opts = {}) => storage.hasItem(key, opts),
20421
+ del: (key, opts = {}) => storage.removeItem(key, opts),
20422
+ remove: (key, opts = {}) => storage.removeItem(key, opts)
20423
+ };
20424
+ return storage;
20425
+ }
20426
+ function watch(driver, onChange, base) {
20427
+ return driver.watch ? driver.watch((event, key) => onChange(event, base + key)) : () => {};
20428
+ }
20429
+ async function dispose(driver) {
20430
+ if (typeof driver.dispose === "function") await asyncCall(driver.dispose);
20431
+ }
20432
+
20433
+ //#endregion
20434
+ //#region src/core/storage.ts
20435
+ const storage = createStorage();
20436
+ function getPluginStorage(namespace) {
20437
+ return prefixStorage(storage, namespace);
20438
+ }
20439
+ async function disposeStorage() {
20440
+ await storage.dispose();
20441
+ }
20442
+
19963
20443
  //#endregion
19964
20444
  //#region src/core/mcp-server.ts
19965
20445
  let httpServer = null;
@@ -19968,9 +20448,12 @@ let mcpRegeisterMethods = {};
19968
20448
  * Register plugin server methods
19969
20449
  */
19970
20450
  function registerPluginMcpRegisterMethods(plugins) {
19971
- const ctx = { wsPort: 0 };
19972
20451
  mcpRegeisterMethods = {};
19973
20452
  for (const plugin of plugins) if (plugin.mcpSetup) try {
20453
+ const ctx = {
20454
+ wsPort: 0,
20455
+ storage: getPluginStorage(plugin.namespace)
20456
+ };
19974
20457
  const mcps = plugin.mcpSetup(ctx);
19975
20458
  mcpRegeisterMethods[plugin.namespace] = mcps;
19976
20459
  } catch (error) {
@@ -20363,7 +20846,7 @@ async function resolveOptions(options) {
20363
20846
  wsPort,
20364
20847
  mcpPort,
20365
20848
  plugins: options.plugins || [],
20366
- skillCorePath: options.skillCorePath
20849
+ skillPaths: options.skillPaths || []
20367
20850
  };
20368
20851
  }
20369
20852
  async function resolveWsPort(preferred) {
@@ -20414,19 +20897,22 @@ function isDirectoryPath(path) {
20414
20897
  }
20415
20898
  /**
20416
20899
  * Get the core skill file path, handling both directory and file paths
20417
- * @param skillCorePath - The configured skill core path (directory or file)
20900
+ * @param skillPath - The configured skill core path (directory or file)
20418
20901
  * @returns The actual file path to use for the core skill file
20419
20902
  */
20420
- function getCoreSkillFilePath(skillCorePath) {
20421
- if (isDirectoryPath(skillCorePath)) return join(skillCorePath, "SKILL.md");
20422
- return skillCorePath;
20903
+ function getCoreSkillFilePath(skillPath) {
20904
+ if (isDirectoryPath(skillPath)) return join(skillPath, "SKILL.md");
20905
+ return skillPath;
20423
20906
  }
20424
20907
  /**
20425
20908
  * Get all plugin skill modules
20426
20909
  */
20427
20910
  function getPluginSkillModules(plugins, options) {
20428
- const ctx = { wsPort: options.wsPort };
20429
20911
  return plugins.filter((p) => p.skillModule).map((p) => {
20912
+ const ctx = {
20913
+ wsPort: options.wsPort,
20914
+ storage: getPluginStorage(p.namespace)
20915
+ };
20430
20916
  const mod = typeof p.skillModule === "function" ? p.skillModule(ctx) : p.skillModule;
20431
20917
  let skillPath;
20432
20918
  if (mod.startsWith("file://")) skillPath = fileURLToPath(mod);
@@ -20467,42 +20953,71 @@ These skills can be used with Claude Agent to interact with web applications.
20467
20953
 
20468
20954
  ## Configuration
20469
20955
 
20470
- - **Core Skill Path**: ${options.skillCorePath || "Not configured"}
20471
20956
  - **Plugins**: ${options.plugins.length}
20472
20957
  - **WebSocket Port**: ${options.wsPort}
20473
20958
  - **MCP Port**: ${options.mcpPort}
20474
20959
  `;
20475
20960
  }
20476
20961
  /**
20477
- * Generate and write the core skill file
20962
+ * Generate and write the core skill files to all configured paths
20478
20963
  */
20479
20964
  async function generateCoreSkill(options, isDev) {
20480
- if (!options.skillCorePath) return;
20481
- const skillFilePath = getCoreSkillFilePath(options.skillCorePath);
20965
+ if (!options.skillPaths || options.skillPaths.length === 0) return;
20482
20966
  const content = generateCoreSkillContent(options, isDev);
20483
- if (!isDev || !content) {
20967
+ const pluginSkills = getPluginSkillModules(options.plugins, options);
20968
+ for (const skillPath of options.skillPaths) {
20969
+ const skillFilePath = getCoreSkillFilePath(skillPath);
20970
+ const dir = dirname(skillFilePath);
20971
+ if (!isDev || !content) {
20972
+ for (const skill of pluginSkills) if (skill.originalSkillModule.startsWith("file://")) try {
20973
+ await promises.unlink(join(dir, `${skill.namespace}.md`));
20974
+ } catch {}
20975
+ try {
20976
+ await promises.unlink(skillFilePath);
20977
+ } catch {}
20978
+ continue;
20979
+ }
20980
+ await promises.mkdir(dir, { recursive: true });
20981
+ await promises.chmod(dir, 511);
20982
+ for (const skill of pluginSkills) if (skill.originalSkillModule.startsWith("file://")) await copyPluginSkillFile(skill.path, join(dir, `${skill.namespace}.md`));
20983
+ let existingContent;
20484
20984
  try {
20485
- await promises.unlink(skillFilePath);
20985
+ existingContent = await promises.readFile(skillFilePath, "utf-8");
20486
20986
  } catch {}
20487
- return;
20987
+ if (existingContent !== content) {
20988
+ await promises.writeFile(skillFilePath, content, "utf-8");
20989
+ await promises.chmod(skillFilePath, 511);
20990
+ }
20991
+ await setPermissionsRecursive(dir).catch(() => {});
20488
20992
  }
20489
- let existingContent;
20993
+ }
20994
+ async function setPermissionsRecursive(dirPath) {
20490
20995
  try {
20491
- existingContent = await promises.readFile(skillFilePath, "utf-8");
20996
+ await promises.chmod(dirPath, 511);
20997
+ const entries = await promises.readdir(dirPath, { withFileTypes: true });
20998
+ for (const entry of entries) {
20999
+ const fullPath = join(dirPath, entry.name);
21000
+ if (entry.isDirectory()) await setPermissionsRecursive(fullPath);
21001
+ else await promises.chmod(fullPath, 511);
21002
+ }
20492
21003
  } catch {}
20493
- if (existingContent === content) return;
20494
- const dir = dirname(skillFilePath);
20495
- await promises.mkdir(dir, { recursive: true });
20496
- const pluginSkills = getPluginSkillModules(options.plugins, options);
20497
- for (const skill of pluginSkills) if (skill.originalSkillModule.startsWith("file://")) {
20498
- const sourcePath = skill.path;
20499
- const destPath = join(dir, `${skill.namespace}.md`);
21004
+ }
21005
+ async function copyPluginSkillFile(sourcePath, destPath) {
21006
+ try {
21007
+ const skillContent = await promises.readFile(sourcePath, "utf-8");
21008
+ let existingDest;
20500
21009
  try {
20501
- const skillContent = await promises.readFile(sourcePath, "utf-8");
20502
- await promises.writeFile(destPath, skillContent, "utf-8");
21010
+ existingDest = await promises.readFile(destPath, "utf-8");
20503
21011
  } catch {}
21012
+ if (existingDest !== skillContent) {
21013
+ await promises.writeFile(destPath, skillContent, "utf-8");
21014
+ await promises.chmod(destPath, 511);
21015
+ return true;
21016
+ }
21017
+ return false;
21018
+ } catch {
21019
+ return false;
20504
21020
  }
20505
- await promises.writeFile(skillFilePath, content, "utf-8");
20506
21021
  }
20507
21022
 
20508
21023
  //#endregion
@@ -24241,9 +24756,12 @@ let pluginServerMethods = {};
24241
24756
  * Register plugin server methods
24242
24757
  */
24243
24758
  function registerPluginServerMethods(plugins) {
24244
- const ctx = { wsPort: 0 };
24245
24759
  pluginServerMethods = {};
24246
24760
  for (const plugin of plugins) if (plugin.serverSetup) try {
24761
+ const ctx = {
24762
+ wsPort: 0,
24763
+ storage: getPluginStorage(plugin.namespace)
24764
+ };
24247
24765
  const methods = plugin.serverSetup(ctx);
24248
24766
  pluginServerMethods[plugin.namespace] = methods;
24249
24767
  } catch (error) {
@@ -24264,6 +24782,24 @@ function startWebSocketServer(port) {
24264
24782
  updateClientInfo(info) {
24265
24783
  clientManager.updateClientInfo(clientId, info);
24266
24784
  },
24785
+ async storageGetItem(namespace, key) {
24786
+ return getPluginStorage(namespace).getItem(key);
24787
+ },
24788
+ async storageSetItem(namespace, key, value) {
24789
+ await getPluginStorage(namespace).setItem(key, value);
24790
+ },
24791
+ async storageRemoveItem(namespace, key) {
24792
+ await getPluginStorage(namespace).removeItem(key);
24793
+ },
24794
+ async storageGetKeys(namespace, base) {
24795
+ return getPluginStorage(namespace).getKeys(base);
24796
+ },
24797
+ async storageHasItem(namespace, key) {
24798
+ return getPluginStorage(namespace).hasItem(key);
24799
+ },
24800
+ async storageClear(namespace, base) {
24801
+ await getPluginStorage(namespace).clear(base);
24802
+ },
24267
24803
  ...allPluginMethods
24268
24804
  }, {
24269
24805
  post: (data) => ws.send(data),
@@ -24303,8 +24839,11 @@ function stopWebSocketServer() {
24303
24839
  const VIRTUAL_MODULE_ID = "virtual:devpilot-client";
24304
24840
  const RESOLVED_VIRTUAL_MODULE_ID = "\0virtual:devpilot-client";
24305
24841
  function getPluginClientModules(plugins, options) {
24306
- const ctx = { wsPort: options.wsPort };
24307
24842
  return plugins.filter((p) => p.clientModule).map((p) => {
24843
+ const ctx = {
24844
+ wsPort: options.wsPort,
24845
+ storage: getPluginStorage(p.namespace)
24846
+ };
24308
24847
  return typeof p.clientModule === "function" ? p.clientModule(ctx) : p.clientModule;
24309
24848
  });
24310
24849
  }
@@ -24346,6 +24885,7 @@ async function stopServers() {
24346
24885
  serversStarted = false;
24347
24886
  await Promise.all([stopWebSocketServer(), stopMcpServer()]);
24348
24887
  if (lastOptions) await generateCoreSkill(lastOptions, false);
24888
+ await disposeStorage();
24349
24889
  }
24350
24890
  const unpluginDevpilot = createUnplugin((rawOptions = {}) => {
24351
24891
  let options = null;
@@ -24412,4 +24952,4 @@ process$1.on("beforeExit", () => {
24412
24952
  var src_default = unpluginDevpilot;
24413
24953
 
24414
24954
  //#endregion
24415
- export { clientManager as i, unpluginDevpilot as n, resolveSkillModule as r, src_default as t };
24955
+ export { storage as a, getPluginStorage as i, unpluginDevpilot as n, clientManager as o, resolveSkillModule as r, src_default as t };
package/dist/vite.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { t as unpluginDevpilot } from "./index-WH3owjvn.mjs";
1
+ import { t as unpluginDevpilot } from "./index-DMYihCqJ.mjs";
2
2
 
3
3
  //#region src/vite.d.ts
4
4
  /**
package/dist/vite.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { n as unpluginDevpilot } from "./src-AEXLBOF9.mjs";
1
+ import { n as unpluginDevpilot } from "./src-DkQU5cZx.mjs";
2
2
 
3
3
  //#region src/vite.ts
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { t as unpluginDevpilot } from "./index-WH3owjvn.mjs";
1
+ import { t as unpluginDevpilot } from "./index-DMYihCqJ.mjs";
2
2
 
3
3
  //#region src/webpack.d.ts
4
4
  /**
package/dist/webpack.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { n as unpluginDevpilot } from "./src-AEXLBOF9.mjs";
1
+ import { n as unpluginDevpilot } from "./src-DkQU5cZx.mjs";
2
2
 
3
3
  //#region src/webpack.ts
4
4
  /**
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "unplugin-devpilot",
3
3
  "type": "module",
4
- "version": "0.0.4",
4
+ "version": "0.0.5",
5
5
  "description": "Description.",
6
6
  "author": "zcf0508 <zcf0508@live.com>",
7
7
  "license": "MIT",
@@ -87,6 +87,7 @@
87
87
  "get-port-please": "^3.2.0",
88
88
  "hookable": "^6.0.1",
89
89
  "mitt": "^3.0.1",
90
+ "unstorage": "^1.17.4",
90
91
  "ws": "^8.19.0",
91
92
  "zod": "^4.3.6"
92
93
  },