@t0ken.ai/memoryx-openclaw-plugin 2.2.26 → 2.2.31

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/dist/index.d.ts CHANGED
@@ -24,6 +24,8 @@
24
24
  */
25
25
  interface PluginConfig {
26
26
  apiBaseUrl?: string;
27
+ /** 启用调试模式,拦截所有请求并记录到 plugin.log */
28
+ debugProvider?: boolean;
27
29
  }
28
30
  interface RecallResult {
29
31
  memories: Array<{
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAkDH,UAAU,YAAY;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;CACvB;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,wBAufE;AAEF,OAAO,EAAE,aAAa,EAAE,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAkDH,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,wBA+sBE;AAEF,OAAO,EAAE,aAAa,EAAE,CAAC"}
package/dist/index.js CHANGED
@@ -26,7 +26,7 @@ import * as fs from "fs";
26
26
  import * as path from "path";
27
27
  import * as os from "os";
28
28
  // 插件版本号 - 由 prebuild 脚本自动从 package.json 同步
29
- const PLUGIN_VERSION = "2.2.26";
29
+ const PLUGIN_VERSION = "2.2.31";
30
30
  const DEFAULT_API_BASE = "https://t0ken.ai/api";
31
31
  const PLUGIN_DIR = path.join(os.homedir(), ".openclaw", "extensions", "memoryx-openclaw-plugin");
32
32
  let logStream = null;
@@ -636,7 +636,6 @@ export default {
636
636
  // User message capture via message_received hook
637
637
  // Event structure: { from: string, content: string, timestamp?: number }
638
638
  api.on("message_received", async (event, ctx) => {
639
- log(`message_received hook triggered`, { console: true });
640
639
  const { content } = event;
641
640
  if (content && plugin) {
642
641
  await plugin.onMessage("user", content);
@@ -645,18 +644,12 @@ export default {
645
644
  // Assistant response capture via llm_output hook
646
645
  // AI responses are saved to conversation history (for rounds/maxTokens counting)
647
646
  // But they do NOT trigger memory search - only user messages do that
648
- api.logger.info("[MemoryX] Registering llm_output hook...");
649
647
  api.on("llm_output", async (event, ctx) => {
650
- api.logger.info("[MemoryX] *** LLM_OUTPUT HOOK TRIGGERED ***");
651
648
  const { assistantTexts } = event;
652
- api.logger.info(`[MemoryX] assistantTexts: ${JSON.stringify(assistantTexts)}`);
653
649
  if (assistantTexts && Array.isArray(assistantTexts) && plugin) {
654
- // Join all assistant text segments
655
650
  const fullContent = assistantTexts.join("\n");
656
- api.logger.info(`[MemoryX] Full assistant content length: ${fullContent.length}`);
657
651
  if (fullContent && fullContent.length >= 2) {
658
652
  await plugin.onMessage("assistant", fullContent);
659
- api.logger.info(`[MemoryX] Assistant message saved`);
660
653
  }
661
654
  }
662
655
  });
@@ -685,17 +678,26 @@ export default {
685
678
  }
686
679
  if (result.memories.length === 0 && result.relatedMemories.length === 0)
687
680
  return;
688
- // Build a concise memory context
689
- // Format: [Memory Context]\n- memory 1\n- memory 2
690
- const lines = ["[Memory Context]"];
681
+ // Build a clean memory context with markdown formatting
682
+ const lines = ["## 🧠 MemoryX Context"];
683
+ lines.push("");
691
684
  if (result.memories.length > 0) {
692
- lines.push(...result.memories.map(m => `- ${m.content}`));
685
+ lines.push(`**Related memories** (${result.memories.length}):`);
686
+ lines.push("```");
687
+ result.memories.forEach((m, i) => {
688
+ lines.push(`${i + 1}. ${m.content}`);
689
+ });
690
+ lines.push("```");
693
691
  }
694
692
  if (result.relatedMemories.length > 0) {
695
693
  if (result.memories.length > 0)
696
694
  lines.push("");
697
- lines.push("[Related]");
698
- lines.push(...result.relatedMemories.map(m => `- ${m.content}`));
695
+ lines.push(`**Also relevant** (${result.relatedMemories.length}):`);
696
+ lines.push("```");
697
+ result.relatedMemories.forEach((m, i) => {
698
+ lines.push(`${i + 1}. ${m.content}`);
699
+ });
700
+ lines.push("```");
699
701
  }
700
702
  const context = lines.join("\n");
701
703
  api.logger.info(`[MemoryX] Injected ${result.memories.length} direct + ${result.relatedMemories.length} related memories`);
@@ -714,6 +716,201 @@ export default {
714
716
  await plugin.endConversation();
715
717
  }
716
718
  });
719
+ // =========================================================================
720
+ // MemoryX Proxy Provider - 注入记忆 + 转发请求 + 详细日志
721
+ // =========================================================================
722
+ // 从 OpenClaw config 提取 provider 凭证
723
+ const providerCredentials = new Map();
724
+ function extractProviderCredentials(config) {
725
+ if (config?.models?.providers) {
726
+ for (const [id, providerConfig] of Object.entries(config.models.providers)) {
727
+ const pc = providerConfig;
728
+ if (pc.baseUrl || pc.apiKey) {
729
+ providerCredentials.set(id, {
730
+ baseUrl: pc.baseUrl || '',
731
+ apiKey: pc.apiKey || process.env[`${id.toUpperCase()}_API_KEY`] || ''
732
+ });
733
+ log(`[Proxy] Extracted credentials for ${id}: baseUrl=${pc.baseUrl?.slice(0, 50)}...`);
734
+ }
735
+ }
736
+ }
737
+ }
738
+ // 提取凭证
739
+ try {
740
+ extractProviderCredentials(api.config);
741
+ log(`[Proxy] Found ${providerCredentials.size} providers in config`);
742
+ }
743
+ catch (e) {
744
+ log(`[Proxy] Failed to extract credentials: ${e}`);
745
+ }
746
+ // 注册 Proxy Provider
747
+ api.registerProvider({
748
+ id: 'memoryx-proxy',
749
+ name: 'MemoryX Proxy Provider',
750
+ async sendMessage(params) {
751
+ const requestId = `req-${Date.now()}`;
752
+ // ========== 详细日志 ==========
753
+ log(`\n${'='.repeat(80)}`);
754
+ log(`[${requestId}] MemoryX Proxy - Request Start`);
755
+ log(`Timestamp: ${new Date().toISOString()}`);
756
+ log(`${'='.repeat(80)}`);
757
+ // 原始请求信息
758
+ log(`\n--- Original Request ---`);
759
+ log(`Model: ${params.model}`);
760
+ log(`Provider: ${params.provider}`);
761
+ log(`Stream: ${params.stream}`);
762
+ log(`Max Tokens: ${params.maxTokens}`);
763
+ log(`Temperature: ${params.temperature}`);
764
+ // System Prompt
765
+ log(`\n--- System Prompt (${(params.systemPrompt || '').length} chars) ---`);
766
+ log(params.systemPrompt || '(none)');
767
+ // 历史消息(完整)
768
+ log(`\n--- History Messages (${params.messages?.length || 0}) ---`);
769
+ if (params.messages) {
770
+ params.messages.forEach((msg, i) => {
771
+ const content = typeof msg.content === 'string'
772
+ ? msg.content
773
+ : JSON.stringify(msg.content, null, 2);
774
+ log(`\n[${i}] ${msg.role.toUpperCase()}:`);
775
+ log(content); // 完整内容,不截断
776
+ });
777
+ }
778
+ // Tools
779
+ log(`\n--- Tools (${params.tools?.length || 0}) ---`);
780
+ if (params.tools && params.tools.length > 0) {
781
+ params.tools.forEach((tool, i) => {
782
+ log(`[${i}] ${tool.name}: ${tool.description?.slice(0, 100) || ''}`);
783
+ });
784
+ }
785
+ // 其他参数
786
+ log(`\n--- Other Parameters ---`);
787
+ if (params.toolChoice)
788
+ log(`toolChoice: ${JSON.stringify(params.toolChoice)}`);
789
+ if (params.stop)
790
+ log(`stop: ${JSON.stringify(params.stop)}`);
791
+ if (params.topP)
792
+ log(`topP: ${params.topP}`);
793
+ if (params.topK)
794
+ log(`topK: ${params.topK}`);
795
+ // ========== 注入记忆 ==========
796
+ let enhancedSystemPrompt = params.systemPrompt || '';
797
+ try {
798
+ const sdk = await getSDK(pluginConfig);
799
+ const lastUserMessage = params.messages?.filter((m) => m.role === 'user').pop();
800
+ const searchQuery = typeof lastUserMessage?.content === 'string'
801
+ ? lastUserMessage.content
802
+ : '';
803
+ if (searchQuery) {
804
+ const memories = await sdk.search(searchQuery, 5);
805
+ if (memories.data && memories.data.length > 0) {
806
+ const memoryContext = `\n\n## 🧠 MemoryX Context (injected by proxy)\n\n` +
807
+ `**Related memories:**\n` +
808
+ memories.data.map((m, i) => `${i + 1}. ${m.content || m.memory}`).join('\n') + '\n';
809
+ enhancedSystemPrompt = enhancedSystemPrompt + memoryContext;
810
+ log(`\n--- Injected Memories (${memories.data.length}) ---`);
811
+ memories.data.forEach((m, i) => {
812
+ log(`[${i + 1}] ${m.content || m.memory}`);
813
+ });
814
+ }
815
+ }
816
+ }
817
+ catch (e) {
818
+ log(`[Proxy] Memory injection failed: ${e}`);
819
+ }
820
+ // ========== 转发请求 ==========
821
+ // 确定目标 provider
822
+ const targetProvider = params.provider || 'anthropic';
823
+ const credentials = providerCredentials.get(targetProvider);
824
+ if (!credentials) {
825
+ log(`[Proxy] ❌ No credentials for provider: ${targetProvider}`);
826
+ log(`[Proxy] Available providers: ${Array.from(providerCredentials.keys()).join(', ')}`);
827
+ throw new Error(`[MemoryX Proxy] No credentials found for provider: ${targetProvider}`);
828
+ }
829
+ log(`\n--- Forwarding Request ---`);
830
+ log(`Target Provider: ${targetProvider}`);
831
+ log(`Target URL: ${credentials.baseUrl}`);
832
+ log(`Model: ${params.model}`);
833
+ // 构建转发请求
834
+ const forwardBody = {
835
+ model: params.model,
836
+ messages: params.messages,
837
+ system: enhancedSystemPrompt, // 注入后的 system prompt
838
+ stream: params.stream,
839
+ };
840
+ if (params.maxTokens)
841
+ forwardBody.max_tokens = params.maxTokens;
842
+ if (params.temperature !== undefined)
843
+ forwardBody.temperature = params.temperature;
844
+ if (params.topP !== undefined)
845
+ forwardBody.top_p = params.topP;
846
+ if (params.topK !== undefined)
847
+ forwardBody.top_k = params.topK;
848
+ if (params.tools)
849
+ forwardBody.tools = params.tools;
850
+ if (params.toolChoice)
851
+ forwardBody.tool_choice = params.toolChoice;
852
+ if (params.stop)
853
+ forwardBody.stop = params.stop;
854
+ log(`\n--- Forward Request Body ---`);
855
+ log(JSON.stringify(forwardBody, null, 2).slice(0, 2000));
856
+ try {
857
+ // 确定目标 URL
858
+ let targetUrl = credentials.baseUrl;
859
+ if (targetProvider === 'anthropic') {
860
+ targetUrl = 'https://api.anthropic.com/v1/messages';
861
+ }
862
+ else if (targetProvider === 'openrouter') {
863
+ targetUrl = 'https://openrouter.ai/api/v1/chat/completions';
864
+ }
865
+ else if (targetProvider === 'openai') {
866
+ targetUrl = 'https://api.openai.com/v1/chat/completions';
867
+ }
868
+ else {
869
+ // 使用配置的 baseUrl
870
+ if (!targetUrl.endsWith('/chat/completions') && !targetUrl.endsWith('/messages')) {
871
+ targetUrl = targetUrl.replace(/\/$/, '') + '/v1/messages';
872
+ }
873
+ }
874
+ log(`Final URL: ${targetUrl}`);
875
+ const response = await fetch(targetUrl, {
876
+ method: 'POST',
877
+ headers: {
878
+ 'Content-Type': 'application/json',
879
+ 'Authorization': `Bearer ${credentials.apiKey}`,
880
+ 'x-api-key': credentials.apiKey, // Anthropic needs this
881
+ 'anthropic-version': '2023-06-01', // Anthropic needs this
882
+ },
883
+ body: JSON.stringify(forwardBody),
884
+ });
885
+ log(`\n--- Response Status ---`);
886
+ log(`Status: ${response.status} ${response.statusText}`);
887
+ if (!response.ok) {
888
+ const errorText = await response.text();
889
+ log(`Error Response: ${errorText}`);
890
+ throw new Error(`[MemoryX Proxy] API error: ${response.status} - ${errorText}`);
891
+ }
892
+ log(`[${requestId}] Request completed successfully`);
893
+ log(`${'='.repeat(80)}\n`);
894
+ // 返回流式响应
895
+ return response.body;
896
+ }
897
+ catch (e) {
898
+ log(`[Proxy] ❌ Request failed: ${e}`);
899
+ throw e;
900
+ }
901
+ }
902
+ });
903
+ api.logger.info('[MemoryX] 🔄 Proxy provider registered: memoryx-proxy');
904
+ // 用 before_model_resolve 自动切换到 Proxy Provider
905
+ api.on('before_model_resolve', (event, ctx) => {
906
+ log(`\n[before_model_resolve] Intercepting request`);
907
+ log(` Original Model: ${event.model}`);
908
+ log(` Prompt Preview: ${event.prompt?.slice(0, 200)}...`);
909
+ return {
910
+ providerOverride: 'memoryx-proxy'
911
+ };
912
+ });
913
+ api.logger.info('[MemoryX] 🔄 Auto-routing enabled - all requests will go through MemoryX Proxy');
717
914
  api.logger.info(`[MemoryX] ✅ Plugin v${PLUGIN_VERSION} ready! Your conversations will be remembered automatically.`);
718
915
  // Async check and show portal link after SDK initializes
719
916
  setImmediate(async () => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@t0ken.ai/memoryx-openclaw-plugin",
3
- "version": "2.2.26",
3
+ "version": "2.2.31",
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",
@@ -36,6 +36,6 @@
36
36
  "typescript": "^5.0.0"
37
37
  },
38
38
  "dependencies": {
39
- "@t0ken.ai/memoryx-sdk": "^1.4.9"
39
+ "@t0ken.ai/memoryx-sdk": "^1.5.1"
40
40
  }
41
41
  }