@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 +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +63 -169
- package/openclaw.plugin.json +1 -1
- package/package.json +1 -1
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
|
package/dist/index.d.ts.map
CHANGED
|
@@ -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,
|
|
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.
|
|
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
|
-
|
|
665
|
-
|
|
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}
|
|
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
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
if (
|
|
930
|
-
|
|
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
|
|
960
|
-
model
|
|
961
|
-
availableProviders: this.availableProviders,
|
|
954
|
+
provider,
|
|
955
|
+
model,
|
|
956
|
+
availableProviders: this.availableProviders,
|
|
962
957
|
credentials: credentialsObj,
|
|
963
958
|
body: openaiRequest,
|
|
964
|
-
searchQuery
|
|
959
|
+
searchQuery,
|
|
965
960
|
agent_id: agentId
|
|
966
961
|
};
|
|
967
|
-
log(`[${requestId}] Forwarding to ${PROXY_URL}`);
|
|
968
|
-
log(`[${requestId}
|
|
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
|
-
//
|
|
1044
|
-
//
|
|
1045
|
-
//
|
|
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
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
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
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
baseUrl
|
|
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
|
-
|
|
1149
|
-
|
|
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
|
-
}
|
|
1161
|
-
|
|
1162
|
-
api.
|
|
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 {
|
package/openclaw.plugin.json
CHANGED
package/package.json
CHANGED