@t0ken.ai/memoryx-openclaw-plugin 2.2.56 → 2.2.58

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
@@ -168,6 +168,10 @@ Memories are categorized by the server:
168
168
  - Minimum 2 characters per message
169
169
  - Short messages like "ok", "thanks" are skipped
170
170
 
171
+ ## How the proxy works (no virtual model)
172
+
173
+ The plugin does **not** add a virtual model. It redirects your existing provider's request URL to a local Sidecar (port 3335). You keep using your configured model (e.g. `zai/glm-5`); the request is sent to the Sidecar with a header identifying the real provider, then the Sidecar forwards to the MemoryX server with your credentials. No need to add `memoryx-proxy` to config or auth.
174
+
171
175
  ## License
172
176
 
173
177
  MIT
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAmDH,UAAU,YAAY;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,mCAAmC;IACnC,aAAa,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,UAAU,YAAY;IAClB,QAAQ,EAAE,KAAK,CAAC;QACZ,EAAE,EAAE,MAAM,CAAC;QACX,OAAO,EAAE,MAAM,CAAC;QAChB,QAAQ,EAAE,MAAM,CAAC;QACjB,KAAK,EAAE,MAAM,CAAC;KACjB,CAAC,CAAC;IACH,eAAe,EAAE,KAAK,CAAC;QACnB,EAAE,EAAE,MAAM,CAAC;QACX,OAAO,EAAE,MAAM,CAAC;QAChB,QAAQ,EAAE,MAAM,CAAC;QACjB,KAAK,EAAE,MAAM,CAAC;KACjB,CAAC,CAAC;IACH,SAAS,EAAE,OAAO,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;CACxB;AAqDD,cAAM,aAAa;IACf,OAAO,CAAC,YAAY,CAA2B;IAC/C,OAAO,CAAC,WAAW,CAAkB;IACrC,OAAO,CAAC,aAAa,CAAkB;gBAE3B,YAAY,CAAC,EAAE,YAAY;IAIjC,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAad,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC;IAUpC,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IA6B1D,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,GAAE,MAAU,GAAG,OAAO,CAAC,YAAY,CAAC;IAyC/D,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC;IAYhC,MAAM,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAc1C,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAcvE,IAAI,CAAC,KAAK,GAAE,MAAW,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAiBxC,cAAc,IAAI,OAAO,CAAC;QACnC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;QACtB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;QACvB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;QACzB,WAAW,EAAE,OAAO,CAAC;QACrB,KAAK,CAAC,EAAE,GAAG,CAAC;KACf,CAAC;IAwBW,cAAc,IAAI,OAAO,CAAC;QACnC,OAAO,EAAE,OAAO,CAAC;QACjB,IAAI,CAAC,EAAE;YACH,QAAQ,EAAE,MAAM,CAAC;YACjB,IAAI,EAAE,MAAM,CAAC;YACb,UAAU,EAAE,MAAM,CAAC;YACnB,YAAY,EAAE,MAAM,CAAC;YACrB,iBAAiB,EAAE,MAAM,CAAC;YAC1B,gBAAgB,EAAE,MAAM,CAAC;YACzB,mBAAmB,EAAE,MAAM,CAAC;YAC5B,MAAM,EAAE,MAAM,CAAC;YACf,OAAO,EAAE,MAAM,CAAC;SACnB,CAAC;QACF,KAAK,CAAC,EAAE,MAAM,CAAC;KAClB,CAAC;CAcL;;;;;;kBAUiB,GAAG,iBAAiB,YAAY,GAAG,IAAI;;AANzD,wBA6gCE;AAEF,OAAO,EAAE,aAAa,EAAE,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAmDH,UAAU,YAAY;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,mCAAmC;IACnC,aAAa,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,UAAU,YAAY;IAClB,QAAQ,EAAE,KAAK,CAAC;QACZ,EAAE,EAAE,MAAM,CAAC;QACX,OAAO,EAAE,MAAM,CAAC;QAChB,QAAQ,EAAE,MAAM,CAAC;QACjB,KAAK,EAAE,MAAM,CAAC;KACjB,CAAC,CAAC;IACH,eAAe,EAAE,KAAK,CAAC;QACnB,EAAE,EAAE,MAAM,CAAC;QACX,OAAO,EAAE,MAAM,CAAC;QAChB,QAAQ,EAAE,MAAM,CAAC;QACjB,KAAK,EAAE,MAAM,CAAC;KACjB,CAAC,CAAC;IACH,SAAS,EAAE,OAAO,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;CACxB;AAqDD,cAAM,aAAa;IACf,OAAO,CAAC,YAAY,CAA2B;IAC/C,OAAO,CAAC,WAAW,CAAkB;IACrC,OAAO,CAAC,aAAa,CAAkB;gBAE3B,YAAY,CAAC,EAAE,YAAY;IAIjC,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAad,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC;IAUpC,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IA6B1D,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,GAAE,MAAU,GAAG,OAAO,CAAC,YAAY,CAAC;IAyC/D,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC;IAYhC,MAAM,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAc1C,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAcvE,IAAI,CAAC,KAAK,GAAE,MAAW,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAiBxC,cAAc,IAAI,OAAO,CAAC;QACnC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;QACtB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;QACvB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;QACzB,WAAW,EAAE,OAAO,CAAC;QACrB,KAAK,CAAC,EAAE,GAAG,CAAC;KACf,CAAC;IAwBW,cAAc,IAAI,OAAO,CAAC;QACnC,OAAO,EAAE,OAAO,CAAC;QACjB,IAAI,CAAC,EAAE;YACH,QAAQ,EAAE,MAAM,CAAC;YACjB,IAAI,EAAE,MAAM,CAAC;YACb,UAAU,EAAE,MAAM,CAAC;YACnB,YAAY,EAAE,MAAM,CAAC;YACrB,iBAAiB,EAAE,MAAM,CAAC;YAC1B,gBAAgB,EAAE,MAAM,CAAC;YACzB,mBAAmB,EAAE,MAAM,CAAC;YAC5B,MAAM,EAAE,MAAM,CAAC;YACf,OAAO,EAAE,MAAM,CAAC;SACnB,CAAC;QACF,KAAK,CAAC,EAAE,MAAM,CAAC;KAClB,CAAC;CAcL;;;;;;kBAUiB,GAAG,iBAAiB,YAAY,GAAG,IAAI;;AANzD,wBA25BE;AAEF,OAAO,EAAE,aAAa,EAAE,CAAC"}
package/dist/index.js CHANGED
@@ -27,7 +27,7 @@ import * as path from "path";
27
27
  import * as os from "os";
28
28
  import * as http from "http";
29
29
  // 插件版本号 - 由 prebuild 脚本自动从 package.json 同步
30
- const PLUGIN_VERSION = "2.2.56";
30
+ const PLUGIN_VERSION = "2.2.58";
31
31
  const DEFAULT_API_BASE = "https://t0ken.ai/api";
32
32
  const PLUGIN_DIR = path.join(os.homedir(), ".openclaw", "extensions", "memoryx-openclaw-plugin");
33
33
  let logStream = null;
@@ -661,11 +661,8 @@ export default {
661
661
  // IMPORTANT: 对话流走的是 before_agent_start 事件,不是 message_received!
662
662
  // message_received 只在 auto-reply 功能中触发
663
663
  api.on("before_agent_start", async (event, ctx) => {
664
- const keys = event && typeof event === 'object' ? Object.keys(event).join(', ') : 'n/a';
665
- const model = event?.model ?? event?.resolvedModel ?? 'undefined';
666
- const provider = event?.provider ?? event?.resolvedProvider ?? 'undefined';
667
- api.logger.info(`[MemoryX] 📋 [after resolve? before_agent_start] event keys: ${keys} | model: ${model} | provider: ${provider}`);
668
- log(`[before_agent_start] model=${model} provider=${provider}`);
664
+ // 每次对话前重新把各 provider baseUrl 指到 Sidecar,确保本次请求走代理(quiet 避免每次刷屏)
665
+ applySidecarRedirect({ quiet: true });
669
666
  const { prompt } = event;
670
667
  if (!prompt || prompt.length < 2 || !plugin)
671
668
  return;
@@ -822,19 +819,6 @@ export default {
822
819
  log(`[Proxy] Found ${providerCredentials.size} providers in config`);
823
820
  const defaultProvider = getDefaultModelAndProvider(providerCredentials);
824
821
  log(`[Proxy] Default: ${defaultProvider.provider}/${defaultProvider.model}`);
825
- // 虚拟模型定义:只使用 id='auto',让 OpenClaw 用 provider+'/'+model.id 得到 fullId 'memoryx-proxy/auto'
826
- // (若用 id='memoryx-proxy/auto',部分实现会拼成 'memoryx-proxy/memoryx-proxy/auto' 导致找不到)
827
- const VIRTUAL_MODEL = {
828
- id: 'auto',
829
- name: 'MemoryX Auto Router',
830
- api: 'openai-completions',
831
- reasoning: true,
832
- input: ['text', 'image'],
833
- cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
834
- contextWindow: 200000,
835
- maxTokens: 16384,
836
- };
837
- const VIRTUAL_MODELS = [VIRTUAL_MODEL];
838
822
  const SIDECAR_PORT = 3335;
839
823
  const PROXY_URL = (pluginConfig?.apiBaseUrl || DEFAULT_API_BASE) + '/openclaw/proxy/chat/completions';
840
824
  class SidecarServer {
@@ -909,7 +893,7 @@ export default {
909
893
  }
910
894
  try {
911
895
  log(`\n${'='.repeat(60)}`);
912
- log(`[${requestId}] Sidecar received request`);
896
+ log(`[Sidecar] ${requestId} received POST /v1/chat/completions`, { console: true });
913
897
  // 读取请求体
914
898
  const body = await this.readBody(req);
915
899
  let openaiRequest;
@@ -922,13 +906,25 @@ export default {
922
906
  res.end('Invalid JSON');
923
907
  return;
924
908
  }
925
- // 详细日志:请求体的完整内容
926
- log(`[${requestId}] Request body keys: ${Object.keys(openaiRequest).join(', ')}`);
927
- log(`[${requestId}] Model: ${openaiRequest.model}, Stream: ${openaiRequest.stream}`);
928
- log(`[${requestId}] Messages count: ${openaiRequest.messages?.length || 0}`);
929
- if (openaiRequest.system) {
930
- log(`[${requestId}] System prompt: ${openaiRequest.system.substring(0, 100)}...`);
909
+ // 真实 provider:来自请求头(插件把用户配置的 baseUrl 改成了 Sidecar 并带上此头)
910
+ const rawProvider = req.headers['x-memoryx-real-provider'];
911
+ let provider = rawProvider?.trim() || '';
912
+ let model = openaiRequest.model || this.defaultProvider.model;
913
+ if (!provider && model && model.includes('/')) {
914
+ const idx = model.indexOf('/');
915
+ provider = model.slice(0, idx);
916
+ model = model.slice(idx + 1);
917
+ }
918
+ if (!provider || !this.credentials.has(provider)) {
919
+ provider = this.defaultProvider.provider;
920
+ model = model || this.defaultProvider.model;
931
921
  }
922
+ if (!model && this.credentials.has(provider)) {
923
+ const creds = this.credentials.get(provider);
924
+ model = creds.models?.[0]?.id || creds.models?.[0]?.name || this.defaultProvider.model;
925
+ }
926
+ log(`[${requestId}] Model: ${openaiRequest.model}, Stream: ${openaiRequest.stream} → proxy provider=${provider}, model=${model}`);
927
+ log(`[Sidecar] ${requestId} → ${provider}/${model} (X-MemoryX-Real-Provider: ${rawProvider || 'from body'})`, { console: true });
932
928
  // 获取 SDK 信息(API Key 和 agent_id)
933
929
  const sdk = await getSDK(pluginConfig);
934
930
  const accountInfo = await sdk.getAccountInfo();
@@ -940,7 +936,7 @@ export default {
940
936
  res.end(JSON.stringify({ error: 'MemoryX not initialized' }));
941
937
  return;
942
938
  }
943
- // 构建发送到服务端的请求
939
+ // 构建发送到服务端的请求(使用请求对应的真实 provider/model)
944
940
  const credentialsObj = {};
945
941
  for (const [id, creds] of this.credentials) {
946
942
  credentialsObj[id] = {
@@ -949,23 +945,22 @@ export default {
949
945
  models: creds.models
950
946
  };
951
947
  }
952
- // 提取搜索 query(最后一条用户消息)
953
948
  const messages = openaiRequest.messages || [];
954
949
  const lastUserMsg = [...messages].reverse().find((m) => m.role === 'user');
955
950
  const searchQuery = typeof lastUserMsg?.content === 'string'
956
951
  ? lastUserMsg.content
957
952
  : '';
958
953
  const proxyRequestBody = {
959
- provider: this.defaultProvider.provider,
960
- model: this.defaultProvider.model,
961
- availableProviders: this.availableProviders, // 所有可用 provider 供服务端 fallback
954
+ provider,
955
+ model,
956
+ availableProviders: this.availableProviders,
962
957
  credentials: credentialsObj,
963
958
  body: openaiRequest,
964
- searchQuery: searchQuery,
959
+ searchQuery,
965
960
  agent_id: agentId
966
961
  };
967
- log(`[${requestId}] Forwarding to ${PROXY_URL}`);
968
- log(`[${requestId}] Default: ${this.defaultProvider.provider}/${this.defaultProvider.model}, Available: ${this.availableProviders.map(p => p.provider).join(', ')}`);
962
+ log(`[${requestId}] Forwarding to ${PROXY_URL} (${provider}/${model})`);
963
+ log(`[Sidecar] ${requestId} forwarding to MemoryX proxy...`, { console: true });
969
964
  // 发送到 MemoryX 服务端代理
970
965
  const proxyResponse = await fetch(PROXY_URL, {
971
966
  method: 'POST',
@@ -976,6 +971,7 @@ export default {
976
971
  body: JSON.stringify(proxyRequestBody)
977
972
  });
978
973
  log(`[${requestId}] Response status: ${proxyResponse.status}`);
974
+ log(`[Sidecar] ${requestId} proxy response ${proxyResponse.status}`, { console: true });
979
975
  // 转发响应
980
976
  res.writeHead(proxyResponse.status, {
981
977
  'Content-Type': proxyResponse.headers.get('content-type') || 'application/json'
@@ -1004,10 +1000,12 @@ export default {
1004
1000
  res.end(responseText);
1005
1001
  }
1006
1002
  log(`[${requestId}] ✅ Completed`);
1003
+ log(`[Sidecar] ${requestId} done`, { console: true });
1007
1004
  log(`${'='.repeat(60)}\n`);
1008
1005
  }
1009
1006
  catch (error) {
1010
1007
  log(`[${requestId}] ❌ Error: ${error.message}`);
1008
+ log(`[Sidecar] ${requestId} error: ${error.message}`, { console: true });
1011
1009
  res.writeHead(500, { 'Content-Type': 'application/json' });
1012
1010
  res.end(JSON.stringify({ error: error.message }));
1013
1011
  }
@@ -1040,145 +1038,41 @@ export default {
1040
1038
  }
1041
1039
  });
1042
1040
  // =========================================================================
1043
- // 关键:动态注入 provider 配置到 api.config
1044
- //
1045
- // 部分 OpenClaw 版本中 resolveModel() 只从 cfg.models.providers 查找,
1046
- // 不会使用 registerProvider() 注册的 providers,故此处注入 config。
1047
- // 若虚拟厂商仍不可用,请在 OpenClaw 配置中显式添加:
1048
- // models.providers["memoryx-proxy"]: { baseUrl: "http://localhost:3335/v1", api: "openai-completions", models: [{ id: "auto", name: "MemoryX Auto", ... }] }
1041
+ // 不改虚拟模型:把用户已配置的 provider baseUrl 改成本地 Sidecar,请求头带上真实 provider
1042
+ // 用户继续用 zai/glm-5 等,请求会发到 Sidecar,Sidecar 根据 X-MemoryX-Real-Provider 转发
1043
+ // register before_agent_start 都会执行,确保网关在发请求时用的是被改过的 config
1049
1044
  // =========================================================================
1050
- // ---------- 日志:写 config 前 ----------
1051
- api.logger.info(`[MemoryX] 📋 [1] Before config write - api.config exists: ${!!api.config}`);
1052
- api.logger.info(`[MemoryX] 📋 [1] Before config write - api.config?.models?.providers keys: ${api.config?.models?.providers ? Object.keys(api.config.models.providers).join(', ') : 'N/A'}`);
1053
- if (api.config?.models?.providers) {
1054
- for (const [pid, p] of Object.entries(api.config.models.providers)) {
1055
- const models = p?.models;
1056
- const modelIds = models?.map((m) => m?.id ?? m?.name ?? '?').join(', ') ?? 'none';
1057
- api.logger.info(`[MemoryX] 📋 [1] Before config write - provider "${pid}" models: [${modelIds}]`);
1058
- }
1059
- }
1060
- if (api.config?.models?.providers) {
1061
- api.config.models.providers['memoryx-proxy'] = {
1062
- baseUrl: `http://localhost:${SIDECAR_PORT}/v1`,
1063
- api: 'openai-completions',
1064
- models: VIRTUAL_MODELS
1065
- };
1066
- api.logger.info('[MemoryX] ✅ Injected memoryx-proxy into config.models.providers');
1067
- api.logger.info(`[MemoryX] 📋 [2] After config write - providers keys: ${Object.keys(api.config.models.providers).join(', ')}`);
1068
- const mx = api.config.models.providers['memoryx-proxy'];
1069
- if (mx?.models) {
1070
- const ids = mx.models.map((m) => m?.id ?? '?').join(', ');
1071
- api.logger.info(`[MemoryX] 📋 [2] After config write - memoryx-proxy model ids: [${ids}]`);
1072
- }
1073
- }
1074
- else if (api.config) {
1075
- if (!api.config.models) {
1076
- api.config.models = {};
1077
- }
1078
- if (!api.config.models.providers) {
1079
- api.config.models.providers = {};
1080
- }
1081
- api.config.models.providers['memoryx-proxy'] = {
1082
- baseUrl: `http://localhost:${SIDECAR_PORT}/v1`,
1083
- api: 'openai-completions',
1084
- models: VIRTUAL_MODELS
1085
- };
1086
- api.logger.info('[MemoryX] ✅ Created and injected memoryx-proxy into config.models.providers');
1087
- api.logger.info(`[MemoryX] 📋 [2] After config write - memoryx-proxy model ids: [${VIRTUAL_MODELS.map(m => m.id).join(', ')}]`);
1088
- }
1089
- else {
1090
- api.logger.warn('[MemoryX] ⚠️ api.config not available - resolveModel may fail to find memoryx-proxy');
1091
- }
1092
- // 注入 agents.defaults:必须用完整 model id "provider/model",否则 model-selection 会把 "auto" 当成无 provider 并回退到 anthropic/auto
1093
- if (api.config) {
1094
- if (!api.config.agents) {
1095
- api.config.agents = {};
1096
- }
1097
- const agents = api.config.agents;
1098
- if (!agents.defaults) {
1099
- agents.defaults = {};
1045
+ const sidecarBase = `http://localhost:${SIDECAR_PORT}/v1`;
1046
+ const realProviderHeader = 'X-MemoryX-Real-Provider';
1047
+ const applySidecarRedirect = (opts) => {
1048
+ const creds = extractProviderCredentials(api.config);
1049
+ if (!api.config?.models?.providers || creds.size === 0) {
1050
+ if (!opts?.quiet)
1051
+ log(`[Proxy] No providers to redirect (providers exists: ${!!api.config?.models?.providers}, creds: ${creds.size})`, { console: true });
1052
+ return;
1100
1053
  }
1101
- agents.defaults.model = 'memoryx-proxy/auto';
1102
- agents.defaults.provider = 'memoryx-proxy';
1103
- api.logger.info('[MemoryX] 📋 Injected agents.defaults: model=memoryx-proxy/auto, provider=memoryx-proxy');
1104
- }
1105
- // 注册 Provider - 完全对齐 SlimClaw 格式
1106
- const registeredModelIds = VIRTUAL_MODELS.map(m => m.id).join(', ');
1107
- api.logger.info(`[MemoryX] 📋 [3] Before registerProvider - will register id=memoryx-proxy, model ids: [${registeredModelIds}]`);
1108
- api.registerProvider({
1109
- id: 'memoryx-proxy',
1110
- label: 'MemoryX Proxy Provider',
1111
- aliases: ['mx'],
1112
- envVars: [],
1113
- models: {
1114
- baseUrl: `http://localhost:${SIDECAR_PORT}/v1`,
1115
- api: 'openai-completions',
1116
- models: VIRTUAL_MODELS,
1117
- },
1118
- auth: [{
1119
- id: 'none',
1120
- label: 'No authentication needed (proxy)',
1121
- kind: 'custom',
1122
- run: async () => ({
1123
- profiles: [],
1124
- notes: ['MemoryX proxies through configured providers']
1125
- }),
1126
- }],
1127
- });
1128
- api.logger.info(`[MemoryX] 📋 [3] After registerProvider - registered memoryx-proxy with models: [${registeredModelIds}]`);
1129
- // 延迟再读一次 config,检查是否被后续逻辑覆盖
1130
- setImmediate(() => {
1131
- api.logger.info(`[MemoryX] 📋 [4] setImmediate(after register) - api.config?.models?.providers keys: ${api.config?.models?.providers ? Object.keys(api.config.models.providers).join(', ') : 'N/A'}`);
1132
- if (api.config?.models?.providers) {
1133
- const mx = api.config.models.providers['memoryx-proxy'];
1134
- if (mx) {
1135
- const ids = mx.models?.map((m) => m?.id ?? '?').join(', ') ?? 'none';
1136
- api.logger.info(`[MemoryX] 📋 [4] setImmediate - memoryx-proxy still present, model ids: [${ids}]`);
1137
- }
1138
- else {
1139
- api.logger.warn('[MemoryX] 📋 [4] setImmediate - memoryx-proxy MISSING from config (may have been overwritten)');
1140
- }
1141
- for (const [pid, p] of Object.entries(api.config.models.providers)) {
1142
- const models = p?.models;
1143
- const modelIds = models?.map((m) => m?.id ?? '?').join(', ') ?? 'none';
1144
- api.logger.info(`[MemoryX] 📋 [4] setImmediate - provider "${pid}" models: [${modelIds}]`);
1145
- }
1054
+ const providers = api.config.models.providers;
1055
+ let n = 0;
1056
+ for (const providerId of creds.keys()) {
1057
+ if (providerId === 'memoryx-proxy')
1058
+ continue;
1059
+ const p = providers[providerId];
1060
+ if (!p || typeof p !== 'object')
1061
+ continue;
1062
+ p.baseUrl = sidecarBase;
1063
+ if (!p.headers)
1064
+ p.headers = {};
1065
+ p.headers[realProviderHeader] = providerId;
1066
+ n++;
1067
+ log(`[Proxy] Redirected provider "${providerId}" baseUrl → Sidecar, header ${realProviderHeader}=${providerId}`);
1146
1068
  }
1147
- });
1148
- setTimeout(() => {
1149
- api.logger.info(`[MemoryX] 📋 [5] setTimeout(500ms) - api.config?.models?.providers keys: ${api.config?.models?.providers ? Object.keys(api.config.models.providers).join(', ') : 'N/A'}`);
1150
- if (api.config?.models?.providers) {
1151
- const mx = api.config.models.providers['memoryx-proxy'];
1152
- if (mx) {
1153
- const ids = mx.models?.map((m) => m?.id ?? '?').join(', ') ?? 'none';
1154
- api.logger.info(`[MemoryX] 📋 [5] setTimeout(500ms) - memoryx-proxy still present, model ids: [${ids}]`);
1155
- }
1156
- else {
1157
- api.logger.warn('[MemoryX] 📋 [5] setTimeout(500ms) - memoryx-proxy MISSING (overwritten after load)');
1158
- }
1069
+ if (n > 0 && !opts?.quiet) {
1070
+ api.logger.info(`[MemoryX] ✅ Sidecar redirect applied for ${n} provider(s). Use your configured model (e.g. zai/glm-5).`);
1071
+ log(`[Proxy] Sidecar redirect applied for ${n} provider(s)`, { console: true });
1159
1072
  }
1160
- }, 500);
1161
- // before_model_resolve 钩子 - 自动拦截所有请求
1162
- api.on('before_model_resolve', (event, ctx) => {
1163
- const originalModel = event.model || 'unknown';
1164
- const eventKeys = event && typeof event === 'object' ? Object.keys(event).join(', ') : 'n/a';
1165
- api.logger.info(`[MemoryX] 📋 [before_model_resolve] event keys: ${eventKeys} | original model: ${originalModel} → returning providerOverride=memoryx-proxy, modelOverride=auto`);
1166
- log(`[before_model_resolve] Intercepting: ${originalModel} → memoryx-proxy/auto`);
1167
- return {
1168
- providerOverride: 'memoryx-proxy',
1169
- modelOverride: 'auto'
1170
- };
1171
- });
1172
- // resolve 之后:在 llm_input 打日志(此处应有已解析的 model/provider)
1173
- api.on('llm_input', (event, ctx) => {
1174
- const keys = event && typeof event === 'object' ? Object.keys(event).join(', ') : 'n/a';
1175
- const model = event?.model ?? event?.resolvedModel ?? 'undefined';
1176
- const provider = event?.provider ?? event?.resolvedProvider ?? 'undefined';
1177
- api.logger.info(`[MemoryX] 📋 [after resolve? llm_input] event keys: ${keys} | model: ${model} | provider: ${provider}`);
1178
- log(`[llm_input] model=${model} provider=${provider}`);
1179
- });
1180
- api.logger.info('[MemoryX] 🔄 Auto-intercept enabled - ALL requests go through MemoryX Proxy');
1181
- api.logger.info(`[MemoryX] ✅ Plugin v${PLUGIN_VERSION} ready! Your conversations will be remembered automatically.`);
1073
+ };
1074
+ applySidecarRedirect();
1075
+ api.logger.info(`[MemoryX] Plugin v${PLUGIN_VERSION} ready! Requests go through MemoryX proxy with your configured model.`);
1182
1076
  // Async check and show portal link after SDK initializes
1183
1077
  setImmediate(async () => {
1184
1078
  try {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "id": "memoryx-openclaw-plugin",
3
3
  "name": "MemoryX Real-time Plugin",
4
- "version": "2.2.56",
4
+ "version": "2.2.58",
5
5
  "description": "Real-time memory capture and recall for OpenClaw",
6
6
  "kind": "memory",
7
7
  "main": "./dist/index.js",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@t0ken.ai/memoryx-openclaw-plugin",
3
- "version": "2.2.56",
3
+ "version": "2.2.58",
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",