@t0ken.ai/memoryx-openclaw-plugin 2.2.62 → 2.2.64

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.
@@ -1,4 +1,4 @@
1
- export declare const PLUGIN_VERSION = "2.2.62";
1
+ export declare const PLUGIN_VERSION = "2.2.64";
2
2
  export declare const DEFAULT_API_BASE = "https://t0ken.ai/api";
3
3
  export declare const PLUGIN_DIR: string;
4
4
  /** 真实上游 baseUrl 缓存文件:重启后若配置已被改成 localhost,从此文件恢复各厂商真实地址。 */
package/dist/constants.js CHANGED
@@ -4,7 +4,7 @@
4
4
  import * as path from "path";
5
5
  import * as os from "os";
6
6
  // Plugin version - synced from package.json by prebuild script
7
- export const PLUGIN_VERSION = "2.2.62";
7
+ export const PLUGIN_VERSION = "2.2.64";
8
8
  export const DEFAULT_API_BASE = "https://t0ken.ai/api";
9
9
  export const PLUGIN_DIR = path.join(os.homedir(), ".openclaw", "extensions", "memoryx-openclaw-plugin");
10
10
  /** 真实上游 baseUrl 缓存文件:重启后若配置已被改成 localhost,从此文件恢复各厂商真实地址。 */
package/dist/hooks.d.ts CHANGED
@@ -4,5 +4,5 @@
4
4
  import type { MemoryXPlugin } from "./plugin-core.js";
5
5
  export declare function registerHooks(api: any, plugin: MemoryXPlugin, wrapProvidersWithProxy: () => void, applySidecarRedirect: (opts?: {
6
6
  quiet?: boolean;
7
- }) => void, shouldApplyProxy: () => boolean): void;
7
+ }) => void, shouldApplyProxy: () => boolean, syncRealUpstreamBaseUrlCache?: () => Promise<void>): void;
8
8
  //# sourceMappingURL=hooks.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../src/hooks.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEtD,wBAAgB,aAAa,CACzB,GAAG,EAAE,GAAG,EACR,MAAM,EAAE,aAAa,EACrB,sBAAsB,EAAE,MAAM,IAAI,EAClC,oBAAoB,EAAE,CAAC,IAAI,CAAC,EAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,KAAK,IAAI,EAC1D,gBAAgB,EAAE,MAAM,OAAO,GAChC,IAAI,CAsCN"}
1
+ {"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../src/hooks.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEtD,wBAAgB,aAAa,CACzB,GAAG,EAAE,GAAG,EACR,MAAM,EAAE,aAAa,EACrB,sBAAsB,EAAE,MAAM,IAAI,EAClC,oBAAoB,EAAE,CAAC,IAAI,CAAC,EAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,KAAK,IAAI,EAC1D,gBAAgB,EAAE,MAAM,OAAO,EAC/B,4BAA4B,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GACnD,IAAI,CAuCN"}
package/dist/hooks.js CHANGED
@@ -1,4 +1,4 @@
1
- export function registerHooks(api, plugin, wrapProvidersWithProxy, applySidecarRedirect, shouldApplyProxy) {
1
+ export function registerHooks(api, plugin, wrapProvidersWithProxy, applySidecarRedirect, shouldApplyProxy, syncRealUpstreamBaseUrlCache) {
2
2
  let useVirtualProviderInLastRun = false;
3
3
  api.on("message_received", async (event) => {
4
4
  const { content } = event;
@@ -18,6 +18,7 @@ export function registerHooks(api, plugin, wrapProvidersWithProxy, applySidecarR
18
18
  });
19
19
  api.on("before_agent_start", async (event) => {
20
20
  if (shouldApplyProxy()) {
21
+ await syncRealUpstreamBaseUrlCache?.();
21
22
  wrapProvidersWithProxy();
22
23
  applySidecarRedirect({ quiet: true });
23
24
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAG/C,OAAO,EAAE,aAAa,EAAU,MAAM,kBAAkB,CAAC;;;;;;kBAyBvC,GAAG,iBAAiB,YAAY,GAAG,IAAI;;AARzD,wBAqGE;AAEF,OAAO,EAAE,aAAa,EAAE,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAG/C,OAAO,EAAE,aAAa,EAAU,MAAM,kBAAkB,CAAC;;;;;;kBAsBvC,GAAG,iBAAiB,YAAY,GAAG,IAAI;;AARzD,wBA6FE;AAEF,OAAO,EAAE,aAAa,EAAE,CAAC"}
package/dist/index.js CHANGED
@@ -16,7 +16,7 @@
16
16
  import { PLUGIN_VERSION, DEFAULT_API_BASE, SIDECAR_PORT } from "./constants.js";
17
17
  import { log, LOG_FILE } from "./logger.js";
18
18
  import { MemoryXPlugin, getSDK } from "./plugin-core.js";
19
- import { extractProviderCredentials, getDefaultModelAndProvider, buildRealUpstreamBaseUrlMap, realUpstreamCredentialsForSidecar, loadRealUpstreamBaseUrlCache, saveRealUpstreamBaseUrlCache, isLocalhostBaseUrl, } from "./proxy-credentials.js";
19
+ import { extractProviderCredentials, getDefaultModelAndProvider, realUpstreamCredentialsForSidecar, syncRealUpstreamBaseUrlCacheFromConfig, } from "./proxy-credentials.js";
20
20
  import { createProxyRedirect } from "./proxy-redirect.js";
21
21
  import { SidecarServer } from "./sidecar.js";
22
22
  import { registerHooks } from "./hooks.js";
@@ -43,8 +43,7 @@ export default {
43
43
  log(`[Proxy] Default: ${defaultConfig.provider}/${defaultConfig.model}`);
44
44
  const realProviderHeader = "X-MemoryX-Real-Provider";
45
45
  const sidecarBaseUrl = `http://localhost:${SIDECAR_PORT}`;
46
- const realUpstreamBaseUrlMap = buildRealUpstreamBaseUrlMap(providerCredentials, sidecarBaseUrl);
47
- const realUpstreamCredentials = realUpstreamCredentialsForSidecar(providerCredentials, realUpstreamBaseUrlMap);
46
+ const realUpstreamCredentials = realUpstreamCredentialsForSidecar(providerCredentials, new Map());
48
47
  const proxyUrl = (pluginConfig?.apiBaseUrl || DEFAULT_API_BASE) + "/llm/proxy/chat/completions";
49
48
  const sidecar = new SidecarServer(realUpstreamCredentials, { model: defaultConfig.model, provider: defaultConfig.provider }, defaultConfig.availableProviders, {
50
49
  proxyUrl,
@@ -56,7 +55,8 @@ export default {
56
55
  const { applySidecarRedirect, wrapProvidersWithProxy } = createProxyRedirect(api, getSidecarBase, realProviderHeader);
57
56
  /** 仅当用户当前默认使用的是 memoryx-gateway 时才做拦截/注入,否则不碰配置,避免装完插件就用不了 OpenClaw。 */
58
57
  const shouldApplyProxy = () => getDefaultModelAndProvider(extractProviderCredentials(api.config), api.config).provider === "memoryx-gateway";
59
- registerHooks(api, plugin, wrapProvidersWithProxy, applySidecarRedirect, shouldApplyProxy);
58
+ const syncRealUpstreamBaseUrlCache = () => syncRealUpstreamBaseUrlCacheFromConfig(api.config, getSidecarBase());
59
+ registerHooks(api, plugin, wrapProvidersWithProxy, applySidecarRedirect, shouldApplyProxy, syncRealUpstreamBaseUrlCache);
60
60
  api.registerService({
61
61
  id: "memoryx-sidecar",
62
62
  start: async () => {
@@ -92,18 +92,8 @@ export default {
92
92
  catch (e) {
93
93
  // ignore
94
94
  }
95
- // 仅用「非 localhost」的 baseUrl 更新缓存,避免配置被改成 localhost 时覆盖掉真实地址
96
95
  try {
97
- const cached = await loadRealUpstreamBaseUrlCache();
98
- const merged = new Map(cached);
99
- for (const [id, url] of realUpstreamBaseUrlMap) {
100
- if (id === "memoryx-gateway")
101
- continue;
102
- if (url && !isLocalhostBaseUrl(url, sidecarBaseUrl)) {
103
- merged.set(id, url);
104
- }
105
- }
106
- await saveRealUpstreamBaseUrlCache(merged);
96
+ await syncRealUpstreamBaseUrlCacheFromConfig(api.config, sidecarBaseUrl);
107
97
  }
108
98
  catch (e) {
109
99
  // ignore
@@ -24,14 +24,24 @@ export declare function extractProviderCredentials(config: any, providerOverride
24
24
  export declare function buildRealUpstreamBaseUrlMap(credentials: Map<string, ProviderCredentials>, _sidecarBaseUrl: string): Map<string, string>;
25
25
  /**
26
26
  * 用 init 时缓存的「真实上游 baseUrl 映射表」生成供 Sidecar 使用的 credentials。
27
- * 发给 llm_proxy 的每个厂商的 targetUrl 均来自此映射表(初始化时的真实 baseUrl),不会被 redirect 后的 localhost 覆盖。
27
+ * 发给 llm_proxy base_url_map(各厂商 api_base)均来自此映射表(真实 baseUrl),不会被 redirect 后的 localhost 覆盖。
28
28
  * 用户改配置后重启即可生效。
29
29
  */
30
30
  export declare function realUpstreamCredentialsForSidecar(credentials: Map<string, ProviderCredentials>, realUpstreamBaseUrlMap: Map<string, string>): Map<string, ProviderCredentials>;
31
31
  /**
32
32
  * 从缓存文件加载「厂商 -> 真实 baseUrl」映射。文件不存在或解析失败返回空 Map。
33
+ * 供插件 sync 时使用(先读已有缓存,没有则当空)。
33
34
  */
34
35
  export declare function loadRealUpstreamBaseUrlCache(): Promise<Map<string, string>>;
36
+ /**
37
+ * 从缓存文件加载「厂商 -> 真实 baseUrl」映射;文件不存在、IO 或解析错误时 throw。
38
+ * 供 Sidecar 每次请求读盘使用,不缓存。
39
+ */
40
+ export declare function loadRealUpstreamBaseUrlCacheStrict(): Promise<Map<string, string>>;
41
+ /**
42
+ * 根据 OpenClaw 配置更新 real-upstream-baseurl.json:非 localhost 的 baseUrl 写入/覆盖,localhost 绝不覆盖。
43
+ */
44
+ export declare function syncRealUpstreamBaseUrlCacheFromConfig(config: any, sidecarBaseUrl: string): Promise<void>;
35
45
  /**
36
46
  * 将「厂商 -> 真实 baseUrl」映射写入缓存文件,重启后若配置被改成 localhost 可从此恢复。
37
47
  */
@@ -1 +1 @@
1
- {"version":3,"file":"proxy-credentials.d.ts","sourceRoot":"","sources":["../src/proxy-credentials.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAuCtD,wBAAgB,0BAA0B,CACtC,MAAM,EAAE,GAAG,EACX,iBAAiB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,GAC9F,GAAG,CAAC,MAAM,EAAE,mBAAmB,CAAC,CA0ClC;AAED;;;;;GAKG;AACH,wBAAgB,2BAA2B,CACvC,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,mBAAmB,CAAC,EAC7C,eAAe,EAAE,MAAM,GACxB,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAQrB;AAED;;;;GAIG;AACH,wBAAgB,iCAAiC,CAC7C,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,mBAAmB,CAAC,EAC7C,sBAAsB,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAC5C,GAAG,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAWlC;AAED;;GAEG;AACH,wBAAsB,4BAA4B,IAAI,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAcjF;AAED;;GAEG;AACH,wBAAsB,4BAA4B,CAAC,GAAG,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAgB1F;AAED,6DAA6D;AAC7D,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,OAAO,CAI/E;AAOD,wGAAwG;AACxG,wBAAgB,qBAAqB,CACjC,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,mBAAmB,CAAC,GAC9C,KAAK,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CAc5C;AAED;;;GAGG;AACH,wBAAgB,2BAA2B,CACvC,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,mBAAmB,CAAC,GAC9C,KAAK,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CAU5C;AAoBD,+HAA+H;AAC/H,wBAAgB,0BAA0B,CACtC,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,mBAAmB,CAAC,EAC7C,MAAM,CAAC,EAAE,GAAG,GACb;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,kBAAkB,EAAE,KAAK,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAAE,CA8BrG"}
1
+ {"version":3,"file":"proxy-credentials.d.ts","sourceRoot":"","sources":["../src/proxy-credentials.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAuCtD,wBAAgB,0BAA0B,CACtC,MAAM,EAAE,GAAG,EACX,iBAAiB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,GAC9F,GAAG,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAiDlC;AAED;;;;;GAKG;AACH,wBAAgB,2BAA2B,CACvC,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,mBAAmB,CAAC,EAC7C,eAAe,EAAE,MAAM,GACxB,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAQrB;AAED;;;;GAIG;AACH,wBAAgB,iCAAiC,CAC7C,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,mBAAmB,CAAC,EAC7C,sBAAsB,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAC5C,GAAG,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAWlC;AAED;;;GAGG;AACH,wBAAsB,4BAA4B,IAAI,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAcjF;AAED;;;GAGG;AACH,wBAAsB,kCAAkC,IAAI,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAUvF;AAED;;GAEG;AACH,wBAAsB,sCAAsC,CACxD,MAAM,EAAE,GAAG,EACX,cAAc,EAAE,MAAM,GACvB,OAAO,CAAC,IAAI,CAAC,CAiBf;AAED;;GAEG;AACH,wBAAsB,4BAA4B,CAAC,GAAG,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAgB1F;AAED,6DAA6D;AAC7D,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,OAAO,CAI/E;AAOD,wGAAwG;AACxG,wBAAgB,qBAAqB,CACjC,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,mBAAmB,CAAC,GAC9C,KAAK,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CAc5C;AAED;;;GAGG;AACH,wBAAgB,2BAA2B,CACvC,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,mBAAmB,CAAC,GAC9C,KAAK,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CAU5C;AAoBD,+HAA+H;AAC/H,wBAAgB,0BAA0B,CACtC,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,mBAAmB,CAAC,EAC7C,MAAM,CAAC,EAAE,GAAG,GACb;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,kBAAkB,EAAE,KAAK,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAAE,CA8BrG"}
@@ -35,9 +35,6 @@ function loadAuthProfilesKeys(profilesPath) {
35
35
  export function extractProviderCredentials(config, providerOverrides) {
36
36
  const credentials = new Map();
37
37
  const authKeys = loadAuthProfilesKeys(DEFAULT_AUTH_PROFILES_PATH);
38
- if (authKeys.size > 0) {
39
- log(`[Proxy] Loaded apiKey from auth-profiles for providers: ${[...authKeys.keys()].join(", ")}`);
40
- }
41
38
  if (config?.models?.providers) {
42
39
  for (const [id, providerConfig] of Object.entries(config.models.providers)) {
43
40
  if (typeof providerConfig !== "object" ||
@@ -62,10 +59,17 @@ export function extractProviderCredentials(config, providerOverrides) {
62
59
  apiKey,
63
60
  models: pc.models,
64
61
  });
65
- log(`[Proxy] Extracted credentials for ${id}: models=${pc.models?.length || 0}`);
66
62
  }
67
63
  }
68
64
  }
65
+ if (credentials.size > 0) {
66
+ const parts = [...credentials.entries()].map(([id, c]) => `${id}(${c.models?.length ?? 0})`);
67
+ const authFromProfiles = [...credentials.keys()].filter((id) => authKeys.has(id));
68
+ const summary = authFromProfiles.length > 0
69
+ ? `[Proxy] Credentials: ${parts.join(", ")}; apiKey from auth-profiles: ${authFromProfiles.join(", ")}`
70
+ : `[Proxy] Credentials: ${parts.join(", ")}`;
71
+ log(summary);
72
+ }
69
73
  return credentials;
70
74
  }
71
75
  /**
@@ -86,7 +90,7 @@ export function buildRealUpstreamBaseUrlMap(credentials, _sidecarBaseUrl) {
86
90
  }
87
91
  /**
88
92
  * 用 init 时缓存的「真实上游 baseUrl 映射表」生成供 Sidecar 使用的 credentials。
89
- * 发给 llm_proxy 的每个厂商的 targetUrl 均来自此映射表(初始化时的真实 baseUrl),不会被 redirect 后的 localhost 覆盖。
93
+ * 发给 llm_proxy base_url_map(各厂商 api_base)均来自此映射表(真实 baseUrl),不会被 redirect 后的 localhost 覆盖。
90
94
  * 用户改配置后重启即可生效。
91
95
  */
92
96
  export function realUpstreamCredentialsForSidecar(credentials, realUpstreamBaseUrlMap) {
@@ -103,6 +107,7 @@ export function realUpstreamCredentialsForSidecar(credentials, realUpstreamBaseU
103
107
  }
104
108
  /**
105
109
  * 从缓存文件加载「厂商 -> 真实 baseUrl」映射。文件不存在或解析失败返回空 Map。
110
+ * 供插件 sync 时使用(先读已有缓存,没有则当空)。
106
111
  */
107
112
  export async function loadRealUpstreamBaseUrlCache() {
108
113
  try {
@@ -121,6 +126,45 @@ export async function loadRealUpstreamBaseUrlCache() {
121
126
  return new Map();
122
127
  }
123
128
  }
129
+ /**
130
+ * 从缓存文件加载「厂商 -> 真实 baseUrl」映射;文件不存在、IO 或解析错误时 throw。
131
+ * 供 Sidecar 每次请求读盘使用,不缓存。
132
+ */
133
+ export async function loadRealUpstreamBaseUrlCacheStrict() {
134
+ const raw = await fs.promises.readFile(REAL_UPSTREAM_BASEURL_CACHE_FILE, "utf8");
135
+ const obj = JSON.parse(raw);
136
+ const map = new Map();
137
+ if (obj && typeof obj === "object") {
138
+ for (const [id, url] of Object.entries(obj)) {
139
+ if (id && typeof url === "string" && url.trim())
140
+ map.set(id, url.trim());
141
+ }
142
+ }
143
+ return map;
144
+ }
145
+ /**
146
+ * 根据 OpenClaw 配置更新 real-upstream-baseurl.json:非 localhost 的 baseUrl 写入/覆盖,localhost 绝不覆盖。
147
+ */
148
+ export async function syncRealUpstreamBaseUrlCacheFromConfig(config, sidecarBaseUrl) {
149
+ let cached;
150
+ try {
151
+ cached = await loadRealUpstreamBaseUrlCache();
152
+ }
153
+ catch {
154
+ cached = new Map();
155
+ }
156
+ const credentials = extractProviderCredentials(config);
157
+ const fromConfig = buildRealUpstreamBaseUrlMap(credentials, sidecarBaseUrl);
158
+ const merged = new Map(cached);
159
+ for (const [id, url] of fromConfig) {
160
+ if (id === "memoryx-gateway")
161
+ continue;
162
+ if (url && !isLocalhostBaseUrl(url, sidecarBaseUrl)) {
163
+ merged.set(id, url);
164
+ }
165
+ }
166
+ await saveRealUpstreamBaseUrlCache(merged);
167
+ }
124
168
  /**
125
169
  * 将「厂商 -> 真实 baseUrl」映射写入缓存文件,重启后若配置被改成 localhost 可从此恢复。
126
170
  */
package/dist/sidecar.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  /**
2
- * Local HTTP Sidecar: 仅转发到服务端 proxy(记忆注入),无本地回落。
2
+ * Local HTTP Sidecar: 轻量化转发。只读 base_url_map + credentials,打包发给服务端;
3
+ * 服务端解析 provider、用 api_base 调 LiteLLM(不拼 URL),做记忆注入。无本地解析、无 target。
3
4
  */
4
5
  import type { ProviderCredentials } from "./types.js";
5
6
  import type { PluginConfig } from "./types.js";
@@ -26,15 +27,7 @@ export declare class SidecarServer {
26
27
  start(): Promise<void>;
27
28
  stop(): Promise<void>;
28
29
  getPort(): number;
29
- /**
30
- * 用持久化/合并后的真实上游 baseUrl 映射更新 credentials,避免重启后配置已是 localhost 时仍用旧缓存。
31
- */
32
- updateRealUpstreamBaseUrlMap(map: Map<string, string>): void;
33
- /** For logging: redact headers (Authorization, x-api-key, etc. show as ***) */
34
- private redactHeaders;
35
- /** Build forward request headers from apiKey in OpenClaw style; does not overwrite user config */
36
- private buildForwardHeaders;
37
- /** 仅转发到服务端 proxy(记忆注入),无本地回落。 */
30
+ /** 轻量化:只读 base_url_map + credentials,打包发给服务端;不做 provider 解析、无 target。 */
38
31
  private handleRequest;
39
32
  private readBody;
40
33
  }
@@ -1 +1 @@
1
- {"version":3,"file":"sidecar.d.ts","sourceRoot":"","sources":["../src/sidecar.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AACtD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAI/C,MAAM,MAAM,MAAM,GAAG,CAAC,MAAM,CAAC,EAAE,YAAY,KAAK,OAAO,CAAC,GAAG,CAAC,CAAC;AAE7D,MAAM,WAAW,cAAc;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACzC;AAED,qBAAa,aAAa;IACtB,OAAO,CAAC,MAAM,CAA4B;IAC1C,OAAO,CAAC,WAAW,CAAmC;IACtD,OAAO,CAAC,eAAe,CAAsC;IAC7D,OAAO,CAAC,kBAAkB,CAA6C;IACvE,OAAO,CAAC,OAAO,CAAiB;gBAG5B,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,mBAAmB,CAAC,EAC7C,eAAe,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,EACpD,kBAAkB,EAAE,KAAK,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,EAC9D,OAAO,EAAE,cAAc;IAQrB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAwBtB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAa3B,OAAO,IAAI,MAAM;IAMjB;;OAEG;IACH,4BAA4B,CAAC,GAAG,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI;IAU5D,+EAA+E;IAC/E,OAAO,CAAC,aAAa;IAUrB,kGAAkG;IAClG,OAAO,CAAC,mBAAmB;IAa3B,iCAAiC;YACnB,aAAa;IAmN3B,OAAO,CAAC,QAAQ;CAQnB"}
1
+ {"version":3,"file":"sidecar.d.ts","sourceRoot":"","sources":["../src/sidecar.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AACtD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAK/C,MAAM,MAAM,MAAM,GAAG,CAAC,MAAM,CAAC,EAAE,YAAY,KAAK,OAAO,CAAC,GAAG,CAAC,CAAC;AAE7D,MAAM,WAAW,cAAc;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACzC;AAED,qBAAa,aAAa;IACtB,OAAO,CAAC,MAAM,CAA4B;IAC1C,OAAO,CAAC,WAAW,CAAmC;IACtD,OAAO,CAAC,eAAe,CAAsC;IAC7D,OAAO,CAAC,kBAAkB,CAA6C;IACvE,OAAO,CAAC,OAAO,CAAiB;gBAG5B,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,mBAAmB,CAAC,EAC7C,eAAe,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,EACpD,kBAAkB,EAAE,KAAK,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,EAC9D,OAAO,EAAE,cAAc;IAQrB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAwBtB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAa3B,OAAO,IAAI,MAAM;IAMjB,yEAAyE;YAC3D,aAAa;IAqK3B,OAAO,CAAC,QAAQ;CAQnB"}
package/dist/sidecar.js CHANGED
@@ -1,9 +1,11 @@
1
1
  /**
2
- * Local HTTP Sidecar: 仅转发到服务端 proxy(记忆注入),无本地回落。
2
+ * Local HTTP Sidecar: 轻量化转发。只读 base_url_map + credentials,打包发给服务端;
3
+ * 服务端解析 provider、用 api_base 调 LiteLLM(不拼 URL),做记忆注入。无本地解析、无 target。
3
4
  */
4
5
  import * as http from "http";
5
6
  import { SIDECAR_PORT } from "./constants.js";
6
7
  import { log, LOG_FILE } from "./logger.js";
8
+ import { loadRealUpstreamBaseUrlCache } from "./proxy-credentials.js";
7
9
  export class SidecarServer {
8
10
  server = null;
9
11
  credentials;
@@ -58,44 +60,7 @@ export class SidecarServer {
58
60
  ? this.server.address().port
59
61
  : SIDECAR_PORT;
60
62
  }
61
- /**
62
- * 用持久化/合并后的真实上游 baseUrl 映射更新 credentials,避免重启后配置已是 localhost 时仍用旧缓存。
63
- */
64
- updateRealUpstreamBaseUrlMap(map) {
65
- for (const [id, baseUrl] of map) {
66
- const creds = this.credentials.get(id);
67
- if (creds && baseUrl) {
68
- this.credentials.set(id, { ...creds, baseUrl });
69
- }
70
- }
71
- log(`[Sidecar] Updated real upstream baseUrl map for ${map.size} provider(s)`);
72
- }
73
- /** For logging: redact headers (Authorization, x-api-key, etc. show as ***) */
74
- redactHeaders(h) {
75
- const out = {};
76
- const secretKeys = ["authorization", "x-api-key", "cookie"];
77
- for (const [k, v] of Object.entries(h)) {
78
- const lower = k.toLowerCase();
79
- out[k] = secretKeys.some((s) => lower === s || lower.includes("api-key")) ? "***" : v;
80
- }
81
- return out;
82
- }
83
- /** Build forward request headers from apiKey in OpenClaw style; does not overwrite user config */
84
- buildForwardHeaders(provider, apiKey) {
85
- const h = { "Content-Type": "application/json" };
86
- const key = (apiKey || "").trim();
87
- if (!key)
88
- return h;
89
- if (provider === "anthropic") {
90
- h["x-api-key"] = key;
91
- h["anthropic-version"] = "2023-06-01";
92
- }
93
- else {
94
- h["Authorization"] = `Bearer ${key}`;
95
- }
96
- return h;
97
- }
98
- /** 仅转发到服务端 proxy(记忆注入),无本地回落。 */
63
+ /** 轻量化:只读 base_url_map + credentials,打包发给服务端;不做 provider 解析、无 target。 */
99
64
  async handleRequest(req, res) {
100
65
  const url = req.url || "/";
101
66
  const method = req.method?.toUpperCase();
@@ -106,12 +71,12 @@ export class SidecarServer {
106
71
  return;
107
72
  }
108
73
  const reqId = `req-${Date.now()}`;
109
- log(`[Sidecar] ${reqId} Incoming ${method} ${url}`);
110
74
  let body;
111
75
  try {
112
76
  body = await this.readBody(req);
113
77
  }
114
78
  catch (e) {
79
+ log(`[Sidecar] ${reqId} err read body: ${e?.message ?? "Read body failed"}`, { console: true });
115
80
  res.writeHead(502, { "Content-Type": "application/json" });
116
81
  res.end(JSON.stringify({ error: e?.message || "Read body failed" }));
117
82
  return;
@@ -123,61 +88,32 @@ export class SidecarServer {
123
88
  catch {
124
89
  openaiRequest = {};
125
90
  }
126
- const messages = openaiRequest.messages || [];
127
- const roleSeq = messages.map((m) => (m?.role || "?").slice(0, 1)).join("");
128
- const lastMsg = messages.length ? messages[messages.length - 1] : null;
129
- const lastRole = lastMsg ? (lastMsg.role || "?") : "-";
130
- const lastContentLen = lastMsg && lastMsg.content != null
131
- ? typeof lastMsg.content === "string"
132
- ? lastMsg.content.length
133
- : JSON.stringify(lastMsg.content).length
134
- : 0;
135
- const topKeys = Object.keys(openaiRequest).filter((k) => !["messages", "model"].includes(k) && openaiRequest[k] != null);
136
- log(`[Sidecar] ${reqId} request detail: bodyLen=${(body || "").length} messages=${messages.length} roles=${roleSeq} lastRole=${lastRole} lastContentLen=${lastContentLen} model=${openaiRequest.model ?? "-"} stream=${!!openaiRequest.stream} extraKeys=[${topKeys.join(",")}]`);
137
- const rawProvider = req.headers["x-memoryx-real-provider"]?.trim() || "";
138
- const modelStr = openaiRequest.model || "";
139
- let provider = rawProvider || (modelStr.includes("/") ? modelStr.split("/")[0] : "") || "";
140
- if (provider === "memoryx-gateway") {
141
- const real = this.availableProviders.find((p) => p.provider !== "memoryx-gateway");
142
- provider = real ? real.provider : "";
143
- }
144
- if (!provider || !this.credentials.has(provider)) {
145
- provider = this.defaultProvider?.provider || "";
146
- }
147
- if (!provider || !this.credentials.has(provider)) {
148
- for (const [id] of this.credentials) {
149
- if (id !== "memoryx-gateway") {
150
- provider = id;
151
- break;
152
- }
153
- }
154
- }
155
- let creds = provider ? this.credentials.get(provider) : undefined;
156
- if (!creds?.baseUrl?.trim() || !(creds.apiKey ?? "").trim()) {
157
- for (const [id, c] of this.credentials) {
158
- if (id !== "memoryx-gateway" && (c.baseUrl || "").trim() && (c.apiKey ?? "").trim()) {
159
- provider = id;
160
- creds = c;
161
- break;
162
- }
163
- }
164
- }
165
- const baseUrl = (creds?.baseUrl || "").trim();
166
- const apiKey = (creds?.apiKey ?? "").trim();
167
- if (!baseUrl || !apiKey) {
168
- res.writeHead(502, { "Content-Type": "application/json" });
169
- res.end(JSON.stringify({ error: "No upstream" }));
170
- return;
91
+ const stream = !!openaiRequest.stream;
92
+ let baseUrlMap;
93
+ try {
94
+ baseUrlMap = await loadRealUpstreamBaseUrlCache();
171
95
  }
172
- const base = baseUrl.replace(/\/$/, "");
173
- const pathFromOpenClaw = (url.split("?")[0] || "/").trim() || "/";
174
- const targetUrl = base + (pathFromOpenClaw.startsWith("/") ? pathFromOpenClaw : "/" + pathFromOpenClaw);
175
- const currentModel = openaiRequest.model || "";
176
- if (!currentModel || currentModel === "auto" || currentModel.startsWith("memoryx-gateway/")) {
177
- const firstId = creds?.models?.[0]?.id || creds?.models?.[0]?.name;
178
- if (firstId)
179
- openaiRequest.model = firstId;
96
+ catch {
97
+ baseUrlMap = new Map();
98
+ }
99
+ const baseUrlMapObj = {};
100
+ for (const [id, u] of baseUrlMap) {
101
+ if (id && u?.trim())
102
+ baseUrlMapObj[id] = u.trim();
103
+ }
104
+ const credentialsObj = {};
105
+ for (const [id, c] of this.credentials) {
106
+ if (!c)
107
+ continue;
108
+ credentialsObj[id] = {
109
+ apiKey: (c.apiKey ?? "").trim(),
110
+ models: c.models,
111
+ };
180
112
  }
113
+ const rawProvider = req.headers["x-memoryx-real-provider"]?.trim() || "";
114
+ const messages = openaiRequest.messages || [];
115
+ const lastUserMsg = [...messages].reverse().find((m) => m.role === "user");
116
+ const searchQuery = typeof lastUserMsg?.content === "string" ? lastUserMsg.content : "";
181
117
  let memoryxApiKey = "";
182
118
  let agentId = "";
183
119
  try {
@@ -187,25 +123,19 @@ export class SidecarServer {
187
123
  agentId = accountInfo.agentId || "";
188
124
  }
189
125
  catch (_e) {
190
- /* Do not block; proxy may still accept request */
126
+ /* do not block */
191
127
  }
192
- const headers = this.buildForwardHeaders(provider, apiKey);
193
- const lastUserMsg = [...messages].reverse().find((m) => m.role === "user");
194
- const searchQuery = typeof lastUserMsg?.content === "string" ? lastUserMsg.content : "";
195
128
  const proxyRequestBody = {
196
- targetUrl,
197
- api_base: base,
198
- headers,
129
+ base_url_map: baseUrlMapObj,
130
+ credentials: credentialsObj,
199
131
  body: openaiRequest,
200
- searchQuery,
132
+ request_headers: { "x-memoryx-real-provider": rawProvider },
133
+ search_query: searchQuery,
201
134
  agent_id: agentId,
202
135
  available_models: this.availableProviders.map((p) => `${p.provider}/${p.model}`),
203
136
  };
204
- const proxyReqHeaders = { "Content-Type": "application/json", "X-API-Key": memoryxApiKey ? "***" : "" };
205
- log(`[Sidecar] ${reqId} Proxy POST ${proxyUrl}`);
206
- log(`[Sidecar] ${reqId} Proxy request headers: ${JSON.stringify(proxyReqHeaders)}`);
207
- log(`[Sidecar] ${reqId} Proxy body: targetUrl=${targetUrl} model=${openaiRequest.model} stream=${!!openaiRequest.stream} searchQuery.length=${searchQuery.length} agent_id=${agentId || "(empty)"}`);
208
- log(`[Sidecar] ${reqId} Forward headers (to upstream): ${JSON.stringify(this.redactHeaders(headers))}`);
137
+ const pathLog = (req.url || "/").split("?")[0] || "/";
138
+ log(`[Sidecar] ${reqId} ${method} ${pathLog} model=${openaiRequest.model ?? "-"} stream=${stream} → proxy`);
209
139
  let proxyResponse = null;
210
140
  try {
211
141
  proxyResponse = await fetch(proxyUrl, {
@@ -216,10 +146,7 @@ export class SidecarServer {
216
146
  }
217
147
  catch (e) {
218
148
  proxyResponse = null;
219
- log(`[Sidecar] ${reqId} Proxy fetch error: ${e?.message ?? String(e)}`, { console: true });
220
- }
221
- if (proxyResponse) {
222
- log(`[Sidecar] ${reqId} Proxy response status=${proxyResponse.status} ${proxyResponse.statusText}`);
149
+ log(`[Sidecar] ${reqId} err proxy fetch: ${e?.message ?? String(e)}`, { console: true });
223
150
  }
224
151
  const proxyFailed = !proxyResponse || proxyResponse.status >= 500;
225
152
  if (proxyFailed) {
@@ -233,12 +160,12 @@ export class SidecarServer {
233
160
  }
234
161
  }
235
162
  catch (_) {
236
- /* drain failed, ignore */
163
+ /* drain */
237
164
  }
238
165
  }
239
- log(`[Sidecar] ${reqId} Proxy failed, returning error (no local fallback)`, { console: true });
240
166
  const status = proxyResponse?.status ?? 502;
241
167
  const detail = proxyResponse?.statusText || "MemoryX proxy unavailable";
168
+ log(`[Sidecar] ${reqId} ← ${status} proxy failed: ${detail}`, { console: true });
242
169
  res.writeHead(status, { "Content-Type": "application/json" });
243
170
  res.end(JSON.stringify({ error: detail }));
244
171
  return;
@@ -255,9 +182,7 @@ export class SidecarServer {
255
182
  }
256
183
  catch (firstErr) {
257
184
  reader.releaseLock();
258
- log(`[Sidecar] ${reqId} Proxy stream first chunk failed: ${firstErr?.message ?? "timeout"}`, {
259
- console: true,
260
- });
185
+ log(`[Sidecar] ${reqId} err stream first chunk: ${firstErr?.message ?? "timeout"}`, { console: true });
261
186
  res.writeHead(502, { "Content-Type": "application/json" });
262
187
  res.end(JSON.stringify({ error: "MemoryX proxy stream failed" }));
263
188
  return;
@@ -279,7 +204,7 @@ export class SidecarServer {
279
204
  reader.releaseLock();
280
205
  }
281
206
  res.end();
282
- log(`[Sidecar] ${reqId} Proxy stream done, status=${proxy.status}`);
207
+ log(`[Sidecar] ${reqId} ${proxy.status} stream`);
283
208
  return;
284
209
  }
285
210
  if (!proxy.body) {
@@ -287,10 +212,11 @@ export class SidecarServer {
287
212
  "Content-Type": proxy.headers.get("content-type") || "application/json",
288
213
  });
289
214
  res.end();
215
+ log(`[Sidecar] ${reqId} ← ${proxy.status} (no body)`);
290
216
  return;
291
217
  }
292
218
  const text = await proxy.text();
293
- log(`[Sidecar] ${reqId} Proxy done, status=${proxy.status} body.length=${text.length}`);
219
+ log(`[Sidecar] ${reqId} ${proxy.status} body=${text.length}`);
294
220
  res.writeHead(proxy.status, {
295
221
  "Content-Type": proxy.headers.get("content-type") || "application/json",
296
222
  });
@@ -1,14 +1,14 @@
1
1
  /**
2
2
  * 与服务端 llm_proxy 一致的厂商请求体规范化。
3
- * 部分 LLM 厂商非标准 OpenAI 格式,需在此做兼容后再转发;服务端用 LiteLLM,Sidecar 直连时用本模块保证同一套逻辑。
3
+ * 当前插件内无调用方,规范化由服务端 llm_proxy 完成;保留本模块供将来如需在插件侧做兼容时复用。
4
4
  */
5
5
  /**
6
- * 判断是否为 Z.AI GLM-5:按 provider 或 targetUrl 与 model 判断。
6
+ * 判断是否为 Z.AI GLM-5:按 provider 与 model 判断(不再依赖 targetUrl)。
7
7
  */
8
- export declare function isZaiGlm5(provider: string, targetUrl: string, model: string): boolean;
8
+ export declare function isZaiGlm5(provider: string, model: string): boolean;
9
9
  /**
10
- * 按厂商与 URL/model 规范化请求体;与服务端逻辑一致,供 Sidecar 直连时使用。
10
+ * 按厂商与 model 规范化请求体;与服务端逻辑一致。当前插件内无调用,规范化在服务端完成。
11
11
  * 返回规范化后的 body(不修改入参)。
12
12
  */
13
- export declare function normalizeBodyForVendor(provider: string, targetUrl: string, body: Record<string, unknown>): Record<string, unknown>;
13
+ export declare function normalizeBodyForVendor(provider: string, body: Record<string, unknown>): Record<string, unknown>;
14
14
  //# sourceMappingURL=vendor-normalize.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"vendor-normalize.d.ts","sourceRoot":"","sources":["../src/vendor-normalize.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;GAEG;AACH,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAQrF;AA4DD;;;GAGG;AACH,wBAAgB,sBAAsB,CAClC,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAMzB"}
1
+ {"version":3,"file":"vendor-normalize.d.ts","sourceRoot":"","sources":["../src/vendor-normalize.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;GAEG;AACH,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAIlE;AA4DD;;;GAGG;AACH,wBAAgB,sBAAsB,CAClC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAMzB"}
@@ -1,19 +1,14 @@
1
1
  /**
2
2
  * 与服务端 llm_proxy 一致的厂商请求体规范化。
3
- * 部分 LLM 厂商非标准 OpenAI 格式,需在此做兼容后再转发;服务端用 LiteLLM,Sidecar 直连时用本模块保证同一套逻辑。
3
+ * 当前插件内无调用方,规范化由服务端 llm_proxy 完成;保留本模块供将来如需在插件侧做兼容时复用。
4
4
  */
5
5
  /**
6
- * 判断是否为 Z.AI GLM-5:按 provider 或 targetUrl 与 model 判断。
6
+ * 判断是否为 Z.AI GLM-5:按 provider 与 model 判断(不再依赖 targetUrl)。
7
7
  */
8
- export function isZaiGlm5(provider, targetUrl, model) {
8
+ export function isZaiGlm5(provider, model) {
9
9
  const prov = (provider || "").toLowerCase();
10
- const url = (targetUrl || "").toLowerCase();
11
10
  const m = (model || "").toLowerCase();
12
- if (prov === "zai" && (m === "glm-5" || m.endsWith("/glm-5")))
13
- return true;
14
- if ((url.includes("open.bigmodel.cn") || url.includes("api.z.ai")) && (m === "glm-5" || m.endsWith("/glm-5")))
15
- return true;
16
- return false;
11
+ return prov === "zai" && (m === "glm-5" || m.endsWith("/glm-5"));
17
12
  }
18
13
  /**
19
14
  * Z.AI GLM-5 兼容:与 api/app/routers/llm_proxy.py _normalize_body_for_zai_glm5 保持一致。
@@ -70,12 +65,12 @@ function normalizeBodyForZaiGlm5(body) {
70
65
  return out;
71
66
  }
72
67
  /**
73
- * 按厂商与 URL/model 规范化请求体;与服务端逻辑一致,供 Sidecar 直连时使用。
68
+ * 按厂商与 model 规范化请求体;与服务端逻辑一致。当前插件内无调用,规范化在服务端完成。
74
69
  * 返回规范化后的 body(不修改入参)。
75
70
  */
76
- export function normalizeBodyForVendor(provider, targetUrl, body) {
71
+ export function normalizeBodyForVendor(provider, body) {
77
72
  const model = String(body?.model || "").trim();
78
- if (isZaiGlm5(provider, targetUrl, model)) {
73
+ if (isZaiGlm5(provider, model)) {
79
74
  return normalizeBodyForZaiGlm5(body);
80
75
  }
81
76
  return body;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@t0ken.ai/memoryx-openclaw-plugin",
3
- "version": "2.2.62",
3
+ "version": "2.2.64",
4
4
  "description": "MemoryX real-time memory capture and recall plugin for OpenClaw (powered by @t0ken.ai/memoryx-sdk)",
5
5
  "type": "module",
6
6
  "author": "MemoryX Team",