molymemo 1.0.39 → 1.0.41
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/analyzer.d.ts +26 -0
- package/dist/analyzer.d.ts.map +1 -0
- package/dist/analyzer.js +122 -0
- package/dist/analyzer.js.map +1 -0
- package/dist/chat-store.d.ts +26 -0
- package/dist/chat-store.d.ts.map +1 -0
- package/dist/chat-store.js +108 -0
- package/dist/chat-store.js.map +1 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +82 -351
- package/dist/index.js.map +1 -1
- package/dist/push-suggestions.d.ts +13 -0
- package/dist/push-suggestions.d.ts.map +1 -0
- package/dist/push-suggestions.js +96 -0
- package/dist/push-suggestions.js.map +1 -0
- package/package.json +1 -1
- package/skills/molymemo-suggestions/SKILL.md +36 -0
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { PluginLogger } from "./server-client.js";
|
|
2
|
+
import type { HookClientConfig } from "./hook-client.js";
|
|
3
|
+
import type { ChatStore } from "./chat-store.js";
|
|
4
|
+
export interface AnalyzerConfig {
|
|
5
|
+
workspaceDir: string;
|
|
6
|
+
pluginId: string;
|
|
7
|
+
maxSuggestions: number;
|
|
8
|
+
sessionIdleMs: number;
|
|
9
|
+
analysisGapMs: number;
|
|
10
|
+
}
|
|
11
|
+
export declare class Analyzer {
|
|
12
|
+
private config;
|
|
13
|
+
private hookConfig;
|
|
14
|
+
private store;
|
|
15
|
+
private logger;
|
|
16
|
+
private sessionTimers;
|
|
17
|
+
private analysisQueue;
|
|
18
|
+
private processingQueue;
|
|
19
|
+
constructor(config: AnalyzerConfig, hookConfig: HookClientConfig, store: ChatStore, logger: PluginLogger);
|
|
20
|
+
resetSessionTimer(filePath: string): void;
|
|
21
|
+
enqueueAnalysis(filePath: string): void;
|
|
22
|
+
clearTimers(): void;
|
|
23
|
+
private processAnalysisQueue;
|
|
24
|
+
private triggerAgentAnalysis;
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=analyzer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analyzer.d.ts","sourceRoot":"","sources":["../src/analyzer.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAEzD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAEjD,MAAM,WAAW,cAAc;IAC7B,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,qBAAa,QAAQ;IACnB,OAAO,CAAC,MAAM,CAAiB;IAC/B,OAAO,CAAC,UAAU,CAAmB;IACrC,OAAO,CAAC,KAAK,CAAY;IACzB,OAAO,CAAC,MAAM,CAAe;IAE7B,OAAO,CAAC,aAAa,CAAoD;IACzE,OAAO,CAAC,aAAa,CAAgB;IACrC,OAAO,CAAC,eAAe,CAAS;gBAG9B,MAAM,EAAE,cAAc,EACtB,UAAU,EAAE,gBAAgB,EAC5B,KAAK,EAAE,SAAS,EAChB,MAAM,EAAE,YAAY;IAQtB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAYzC,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAUvC,WAAW,IAAI,IAAI;YAOL,oBAAoB;YAwBpB,oBAAoB;CA2EnC"}
|
package/dist/analyzer.js
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import * as path from "node:path";
|
|
2
|
+
import { postAgentHook } from "./hook-client.js";
|
|
3
|
+
export class Analyzer {
|
|
4
|
+
config;
|
|
5
|
+
hookConfig;
|
|
6
|
+
store;
|
|
7
|
+
logger;
|
|
8
|
+
sessionTimers = new Map();
|
|
9
|
+
analysisQueue = [];
|
|
10
|
+
processingQueue = false;
|
|
11
|
+
constructor(config, hookConfig, store, logger) {
|
|
12
|
+
this.config = config;
|
|
13
|
+
this.hookConfig = hookConfig;
|
|
14
|
+
this.store = store;
|
|
15
|
+
this.logger = logger;
|
|
16
|
+
}
|
|
17
|
+
resetSessionTimer(filePath) {
|
|
18
|
+
const existing = this.sessionTimers.get(filePath);
|
|
19
|
+
if (existing)
|
|
20
|
+
clearTimeout(existing);
|
|
21
|
+
const timer = setTimeout(() => {
|
|
22
|
+
this.sessionTimers.delete(filePath);
|
|
23
|
+
this.enqueueAnalysis(filePath);
|
|
24
|
+
}, this.config.sessionIdleMs);
|
|
25
|
+
this.sessionTimers.set(filePath, timer);
|
|
26
|
+
}
|
|
27
|
+
enqueueAnalysis(filePath) {
|
|
28
|
+
if (!this.analysisQueue.includes(filePath)) {
|
|
29
|
+
this.analysisQueue.push(filePath);
|
|
30
|
+
this.logger.info(`Queued analysis for ${filePath} (queue size: ${this.analysisQueue.length})`);
|
|
31
|
+
}
|
|
32
|
+
void this.processAnalysisQueue();
|
|
33
|
+
}
|
|
34
|
+
clearTimers() {
|
|
35
|
+
for (const timer of this.sessionTimers.values()) {
|
|
36
|
+
clearTimeout(timer);
|
|
37
|
+
}
|
|
38
|
+
this.sessionTimers.clear();
|
|
39
|
+
}
|
|
40
|
+
async processAnalysisQueue() {
|
|
41
|
+
if (this.processingQueue)
|
|
42
|
+
return;
|
|
43
|
+
this.processingQueue = true;
|
|
44
|
+
while (this.analysisQueue.length > 0) {
|
|
45
|
+
const filePath = this.analysisQueue.shift();
|
|
46
|
+
try {
|
|
47
|
+
await this.triggerAgentAnalysis(filePath);
|
|
48
|
+
}
|
|
49
|
+
catch (err) {
|
|
50
|
+
this.logger.error(`Agent analysis error for ${filePath}: ${err}`);
|
|
51
|
+
}
|
|
52
|
+
if (this.analysisQueue.length > 0) {
|
|
53
|
+
this.logger.info(`Waiting ${this.config.analysisGapMs / 1000}s before next analysis (${this.analysisQueue.length} remaining)`);
|
|
54
|
+
await new Promise((resolve) => setTimeout(resolve, this.config.analysisGapMs));
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
this.processingQueue = false;
|
|
58
|
+
}
|
|
59
|
+
async triggerAgentAnalysis(filePath) {
|
|
60
|
+
const meta = this.store.readMeta(filePath);
|
|
61
|
+
if (meta?.analyzed_at && meta.analyzed_at >= meta.latest_at) {
|
|
62
|
+
this.logger.info(`Skipping analysis for ${filePath}: already analyzed at ${meta.analyzed_at}`);
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
const { workspaceDir, pluginId, maxSuggestions } = this.config;
|
|
66
|
+
const dataFilePath = path.join(this.store.getDataDir(), filePath);
|
|
67
|
+
const suggestionsPath = this.store.getSuggestionsPath();
|
|
68
|
+
const memoryBaseDir = path.join(workspaceDir, "memory", pluginId);
|
|
69
|
+
const memoryFilePath = path.join(memoryBaseDir, filePath);
|
|
70
|
+
const message = [
|
|
71
|
+
"You are analyzing an AI chat session file for valuable insights and proactive opportunities.",
|
|
72
|
+
"",
|
|
73
|
+
`Read the file at ${dataFilePath} and analyze the recent conversation content.`,
|
|
74
|
+
"",
|
|
75
|
+
"## Task 1: Long-term Memory Extraction",
|
|
76
|
+
`Write valuable findings as a Markdown file to ${memoryFilePath} (auto-indexed as long-term memory). Create parent directories if needed.`,
|
|
77
|
+
"Focus on: key decisions, learned facts, user preferences, domain knowledge, and recurring patterns.",
|
|
78
|
+
"",
|
|
79
|
+
"## Task 2: Proactive Suggestions",
|
|
80
|
+
`Read the current suggestion list at ${suggestionsPath} (the file may not exist yet — if so, create it). Then update it with new suggestions.`,
|
|
81
|
+
"",
|
|
82
|
+
"Suggestions should focus on what OpenClaw can **proactively do next** for the user, such as:",
|
|
83
|
+
"- Create a specialized Agent Skill based on topics discussed (e.g. a domain-expert skill for a field the user frequently explores)",
|
|
84
|
+
"- Deep-dive research into a topic the user showed interest in but didn't fully explore",
|
|
85
|
+
"- Set up periodic monitoring or reports (e.g. track price changes, news updates, project status)",
|
|
86
|
+
"- Automate a repetitive workflow the user described",
|
|
87
|
+
"- Connect insights across different chat sessions the user has had",
|
|
88
|
+
"- Suggest relevant tools, resources, or next steps based on the conversation context",
|
|
89
|
+
"",
|
|
90
|
+
`Each suggestion entry must have this structure (context is an array — one entry per source session, multiple if the suggestion spans several conversations):`,
|
|
91
|
+
JSON.stringify({
|
|
92
|
+
id: "unique-id (use timestamp + short hash)",
|
|
93
|
+
name: "Short actionable title",
|
|
94
|
+
content: "What OpenClaw can do and why it's valuable (1-3 sentences)",
|
|
95
|
+
context: [
|
|
96
|
+
{
|
|
97
|
+
platform: "Source AI platform name (e.g. ChatGPT, Gemini)",
|
|
98
|
+
sessionPath: `relative path under chat-data/, e.g. ChatGPT/abc123.md (current file: ${filePath})`,
|
|
99
|
+
summary: "2-5 sentence summary of the relevant discussion",
|
|
100
|
+
},
|
|
101
|
+
],
|
|
102
|
+
createdAt: "ISO timestamp",
|
|
103
|
+
pushed: false,
|
|
104
|
+
}, null, 2),
|
|
105
|
+
"",
|
|
106
|
+
`Keep the total number of suggestions at most ${maxSuggestions}. Remove the oldest pushed entries first if the limit is exceeded.`,
|
|
107
|
+
"Avoid duplicate or near-duplicate suggestions.",
|
|
108
|
+
"Only add suggestions that are genuinely actionable by OpenClaw.",
|
|
109
|
+
"",
|
|
110
|
+
"IMPORTANT: Respond with only the single word \"done\" after completing your tasks. Do not summarize, chat, or address the user.",
|
|
111
|
+
].join("\n");
|
|
112
|
+
const ok = await postAgentHook(this.hookConfig, { message, name: "MolyMemo-Analyze", deliver: false }, this.logger);
|
|
113
|
+
if (ok) {
|
|
114
|
+
if (meta) {
|
|
115
|
+
meta.analyzed_at = new Date().toISOString();
|
|
116
|
+
this.store.writeMeta(filePath, meta);
|
|
117
|
+
}
|
|
118
|
+
this.logger.info(`Agent analysis triggered for ${filePath}`);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
//# sourceMappingURL=analyzer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analyzer.js","sourceRoot":"","sources":["../src/analyzer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { PluginLogger } from "./server-client.js";
|
|
2
|
+
import type { PullFileResult } from "./server-client.js";
|
|
3
|
+
import type { FileInfo } from "./server-client.js";
|
|
4
|
+
export interface FileMeta {
|
|
5
|
+
path?: string;
|
|
6
|
+
latest_at: string;
|
|
7
|
+
title?: string;
|
|
8
|
+
url?: string;
|
|
9
|
+
analyzed_at?: string;
|
|
10
|
+
}
|
|
11
|
+
export declare class ChatStore {
|
|
12
|
+
private pluginDir;
|
|
13
|
+
private logger;
|
|
14
|
+
constructor(workspaceDir: string, pluginId: string, logger: PluginLogger);
|
|
15
|
+
getPluginDir(): string;
|
|
16
|
+
getDataDir(): string;
|
|
17
|
+
getDataPath(relativePath: string): string;
|
|
18
|
+
getMetaPath(relativePath: string): string;
|
|
19
|
+
getSuggestionsPath(): string;
|
|
20
|
+
ensureDir(filePath: string): void;
|
|
21
|
+
readMeta(relativePath: string): FileMeta | null;
|
|
22
|
+
writeMeta(relativePath: string, meta: FileMeta): void;
|
|
23
|
+
scanLocalFiles(): FileInfo[];
|
|
24
|
+
writeFileData(msg: PullFileResult): void;
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=chat-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chat-store.d.ts","sourceRoot":"","sources":["../src/chat-store.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAInD,MAAM,WAAW,QAAQ;IACvB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,qBAAa,SAAS;IACpB,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,MAAM,CAAe;gBAEjB,YAAY,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY;IAKxE,YAAY,IAAI,MAAM;IAItB,UAAU,IAAI,MAAM;IAIpB,WAAW,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM;IAIzC,WAAW,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM;IAOzC,kBAAkB,IAAI,MAAM;IAI5B,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAKjC,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI;IAS/C,SAAS,CAAC,YAAY,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,GAAG,IAAI;IAMrD,cAAc,IAAI,QAAQ,EAAE;IA6B5B,aAAa,CAAC,GAAG,EAAE,cAAc,GAAG,IAAI;CAkCzC"}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import * as fs from "node:fs";
|
|
2
|
+
import * as path from "node:path";
|
|
3
|
+
const ZERO_TIME = "0001-01-01T00:00:00Z";
|
|
4
|
+
export class ChatStore {
|
|
5
|
+
pluginDir;
|
|
6
|
+
logger;
|
|
7
|
+
constructor(workspaceDir, pluginId, logger) {
|
|
8
|
+
this.pluginDir = path.join(workspaceDir, pluginId);
|
|
9
|
+
this.logger = logger;
|
|
10
|
+
}
|
|
11
|
+
getPluginDir() {
|
|
12
|
+
return this.pluginDir;
|
|
13
|
+
}
|
|
14
|
+
getDataDir() {
|
|
15
|
+
return path.join(this.pluginDir, "chat-data");
|
|
16
|
+
}
|
|
17
|
+
getDataPath(relativePath) {
|
|
18
|
+
return path.join(this.getDataDir(), relativePath);
|
|
19
|
+
}
|
|
20
|
+
getMetaPath(relativePath) {
|
|
21
|
+
return path.join(this.getDataDir(), relativePath.replace(/\.[^.]+$/, ".meta.json"));
|
|
22
|
+
}
|
|
23
|
+
getSuggestionsPath() {
|
|
24
|
+
return path.join(this.pluginDir, "molymemo-suggestions.json");
|
|
25
|
+
}
|
|
26
|
+
ensureDir(filePath) {
|
|
27
|
+
const dir = path.dirname(filePath);
|
|
28
|
+
if (!fs.existsSync(dir))
|
|
29
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
30
|
+
}
|
|
31
|
+
readMeta(relativePath) {
|
|
32
|
+
try {
|
|
33
|
+
const raw = fs.readFileSync(this.getMetaPath(relativePath), "utf-8");
|
|
34
|
+
return JSON.parse(raw);
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
writeMeta(relativePath, meta) {
|
|
41
|
+
const metaPath = this.getMetaPath(relativePath);
|
|
42
|
+
this.ensureDir(metaPath);
|
|
43
|
+
fs.writeFileSync(metaPath, JSON.stringify(meta) + "\n", "utf-8");
|
|
44
|
+
}
|
|
45
|
+
scanLocalFiles() {
|
|
46
|
+
const dataDir = this.getDataDir();
|
|
47
|
+
if (!fs.existsSync(dataDir)) {
|
|
48
|
+
this.logger.info(`scanLocalFiles: dataDir not found: ${dataDir}`);
|
|
49
|
+
return [];
|
|
50
|
+
}
|
|
51
|
+
const files = [];
|
|
52
|
+
const scanDir = (dir, prefix) => {
|
|
53
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
54
|
+
for (const entry of entries) {
|
|
55
|
+
if (entry.isDirectory()) {
|
|
56
|
+
scanDir(path.join(dir, entry.name), `${prefix}${entry.name}/`);
|
|
57
|
+
}
|
|
58
|
+
else if (entry.isFile() && entry.name.endsWith(".meta.json")) {
|
|
59
|
+
const metaPath = `${prefix}${entry.name.replace(/\.meta\.json$/, ".md")}`;
|
|
60
|
+
const meta = this.readMeta(metaPath);
|
|
61
|
+
if (!meta)
|
|
62
|
+
continue;
|
|
63
|
+
const filePath = meta.path ?? metaPath;
|
|
64
|
+
files.push({
|
|
65
|
+
path: filePath,
|
|
66
|
+
last_sync_at: meta.latest_at ?? "",
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
scanDir(dataDir, "");
|
|
72
|
+
return files;
|
|
73
|
+
}
|
|
74
|
+
writeFileData(msg) {
|
|
75
|
+
if (msg.mode === "none") {
|
|
76
|
+
this.logger.info(`No updates for ${msg.path}`);
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
const dataPath = this.getDataPath(msg.path);
|
|
80
|
+
this.ensureDir(dataPath);
|
|
81
|
+
if (msg.content) {
|
|
82
|
+
if (msg.mode === "append") {
|
|
83
|
+
fs.appendFileSync(dataPath, msg.content, "utf-8");
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
fs.writeFileSync(dataPath, msg.content, "utf-8");
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
const existingMeta = this.readMeta(msg.path);
|
|
90
|
+
const meta = {
|
|
91
|
+
path: msg.path,
|
|
92
|
+
latest_at: msg.latest_at && msg.latest_at !== ZERO_TIME
|
|
93
|
+
? msg.latest_at
|
|
94
|
+
: (existingMeta?.latest_at ?? ""),
|
|
95
|
+
};
|
|
96
|
+
if (msg.title)
|
|
97
|
+
meta.title = msg.title;
|
|
98
|
+
else if (existingMeta?.title)
|
|
99
|
+
meta.title = existingMeta.title;
|
|
100
|
+
if (msg.url)
|
|
101
|
+
meta.url = msg.url;
|
|
102
|
+
else if (existingMeta?.url)
|
|
103
|
+
meta.url = existingMeta.url;
|
|
104
|
+
this.writeMeta(msg.path, meta);
|
|
105
|
+
this.logger.info(`Synced ${msg.path} [${msg.mode}]`);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
//# sourceMappingURL=chat-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chat-store.js","sourceRoot":"","sources":["../src/chat-store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAKlC,MAAM,SAAS,GAAG,sBAAsB,CAAC;AAUzC,MAAM,OAAO,SAAS;IACZ,SAAS,CAAS;IAClB,MAAM,CAAe;IAE7B,YAAY,YAAoB,EAAE,QAAgB,EAAE,MAAoB;QACtE,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC;QACnD,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;IAED,YAAY;QACV,OAAO,IAAI,CAAC,SAAS,CAAC;IACxB,CAAC;IAED,UAAU;QACR,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;IAChD,CAAC;IAED,WAAW,CAAC,YAAoB;QAC9B,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,EAAE,YAAY,CAAC,CAAC;IACpD,CAAC;IAED,WAAW,CAAC,YAAoB;QAC9B,OAAO,IAAI,CAAC,IAAI,CACd,IAAI,CAAC,UAAU,EAAE,EACjB,YAAY,CAAC,OAAO,CAAC,UAAU,EAAE,YAAY,CAAC,CAC/C,CAAC;IACJ,CAAC;IAED,kBAAkB;QAChB,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,2BAA2B,CAAC,CAAC;IAChE,CAAC;IAED,SAAS,CAAC,QAAgB;QACxB,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QACnC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC;YAAE,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAClE,CAAC;IAED,QAAQ,CAAC,YAAoB;QAC3B,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,WAAW,CAAC,YAAY,CAAC,EAAE,OAAO,CAAC,CAAC;YACrE,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAa,CAAC;QACrC,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED,SAAS,CAAC,YAAoB,EAAE,IAAc;QAC5C,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,CAAC,YAAY,CAAC,CAAC;QAChD,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;QACzB,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,IAAI,EAAE,OAAO,CAAC,CAAC;IACnE,CAAC;IAED,cAAc;QACZ,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC;QAClC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;YAC5B,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,sCAAsC,OAAO,EAAE,CAAC,CAAC;YAClE,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,MAAM,KAAK,GAAe,EAAE,CAAC;QAC7B,MAAM,OAAO,GAAG,CAAC,GAAW,EAAE,MAAc,EAAE,EAAE;YAC9C,MAAM,OAAO,GAAG,EAAE,CAAC,WAAW,CAAC,GAAG,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;YAC7D,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;gBAC5B,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;oBACxB,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,EAAE,GAAG,MAAM,GAAG,KAAK,CAAC,IAAI,GAAG,CAAC,CAAC;gBACjE,CAAC;qBAAM,IAAI,KAAK,CAAC,MAAM,EAAE,IAAI,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC;oBAC/D,MAAM,QAAQ,GAAG,GAAG,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,eAAe,EAAE,KAAK,CAAC,EAAE,CAAC;oBAC1E,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;oBACrC,IAAI,CAAC,IAAI;wBAAE,SAAS;oBACpB,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,IAAI,QAAQ,CAAC;oBACvC,KAAK,CAAC,IAAI,CAAC;wBACT,IAAI,EAAE,QAAQ;wBACd,YAAY,EAAE,IAAI,CAAC,SAAS,IAAI,EAAE;qBACnC,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;QACH,CAAC,CAAC;QACF,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;QACrB,OAAO,KAAK,CAAC;IACf,CAAC;IAED,aAAa,CAAC,GAAmB;QAC/B,IAAI,GAAG,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YACxB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,kBAAkB,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;YAC/C,OAAO;QACT,CAAC;QAED,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC5C,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;QAEzB,IAAI,GAAG,CAAC,OAAO,EAAE,CAAC;YAChB,IAAI,GAAG,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBAC1B,EAAE,CAAC,cAAc,CAAC,QAAQ,EAAE,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YACpD,CAAC;iBAAM,CAAC;gBACN,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YACnD,CAAC;QACH,CAAC;QAED,MAAM,YAAY,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAE7C,MAAM,IAAI,GAAa;YACrB,IAAI,EAAE,GAAG,CAAC,IAAI;YACd,SAAS,EACP,GAAG,CAAC,SAAS,IAAI,GAAG,CAAC,SAAS,KAAK,SAAS;gBAC1C,CAAC,CAAC,GAAG,CAAC,SAAS;gBACf,CAAC,CAAC,CAAC,YAAY,EAAE,SAAS,IAAI,EAAE,CAAC;SACtC,CAAC;QACF,IAAI,GAAG,CAAC,KAAK;YAAE,IAAI,CAAC,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC;aACjC,IAAI,YAAY,EAAE,KAAK;YAAE,IAAI,CAAC,KAAK,GAAG,YAAY,CAAC,KAAK,CAAC;QAC9D,IAAI,GAAG,CAAC,GAAG;YAAE,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC;aAC3B,IAAI,YAAY,EAAE,GAAG;YAAE,IAAI,CAAC,GAAG,GAAG,YAAY,CAAC,GAAG,CAAC;QAExD,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QAC/B,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,GAAG,CAAC,IAAI,KAAK,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC;IACvD,CAAC;CACF"}
|
package/dist/index.d.ts
CHANGED
|
@@ -12,14 +12,14 @@ declare const molyMemoPlugin: {
|
|
|
12
12
|
sessionIdleMinutes: z.ZodOptional<z.ZodNumber>;
|
|
13
13
|
}, "strict", z.ZodTypeAny, {
|
|
14
14
|
debug?: boolean | undefined;
|
|
15
|
-
apiKey?: string | undefined;
|
|
16
15
|
maxSuggestions?: number | undefined;
|
|
16
|
+
apiKey?: string | undefined;
|
|
17
17
|
pushIntervalMinutes?: number | undefined;
|
|
18
18
|
sessionIdleMinutes?: number | undefined;
|
|
19
19
|
}, {
|
|
20
20
|
debug?: boolean | undefined;
|
|
21
|
-
apiKey?: string | undefined;
|
|
22
21
|
maxSuggestions?: number | undefined;
|
|
22
|
+
apiKey?: string | undefined;
|
|
23
23
|
pushIntervalMinutes?: number | undefined;
|
|
24
24
|
sessionIdleMinutes?: number | undefined;
|
|
25
25
|
}>;
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AA2B7D,QAAA,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;kBAMJ,iBAAiB;CAkNhC,CAAC;AAEF,eAAe,cAAc,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
import * as fs from "node:fs";
|
|
3
|
-
import * as path from "node:path";
|
|
4
2
|
import { Type } from "@sinclair/typebox";
|
|
5
|
-
import { MolyMemoServerClient
|
|
3
|
+
import { MolyMemoServerClient } from "./server-client.js";
|
|
6
4
|
import { SyncWorker } from "./sync-worker.js";
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
5
|
+
import { ChatStore } from "./chat-store.js";
|
|
6
|
+
import { Analyzer } from "./analyzer.js";
|
|
7
|
+
import { SuggestionPusher } from "./push-suggestions.js";
|
|
9
8
|
const PLUGIN_ID = "molymemo";
|
|
10
9
|
const WS_URL = "wss://idwmmi5m07.execute-api.us-east-1.amazonaws.com/online/";
|
|
11
10
|
const API_URL = "https://internal-api.memo.molyagent.com";
|
|
@@ -20,7 +19,6 @@ const configSchema = z
|
|
|
20
19
|
sessionIdleMinutes: z.number().int().min(1).optional(),
|
|
21
20
|
})
|
|
22
21
|
.strict();
|
|
23
|
-
const ZERO_TIME = "0001-01-01T00:00:00Z";
|
|
24
22
|
const molyMemoPlugin = {
|
|
25
23
|
id: PLUGIN_ID,
|
|
26
24
|
name: "MolyMemo",
|
|
@@ -36,9 +34,12 @@ const molyMemoPlugin = {
|
|
|
36
34
|
const apiKey = (config.apiKey ?? "").trim();
|
|
37
35
|
const debug = config.debug ?? false;
|
|
38
36
|
const maxSuggestions = config.maxSuggestions ?? 10;
|
|
39
|
-
const sessionIdleMs = debug
|
|
40
|
-
|
|
41
|
-
|
|
37
|
+
const sessionIdleMs = debug
|
|
38
|
+
? 60 * 1000
|
|
39
|
+
: (config.sessionIdleMinutes ?? 5) * 60 * 1000;
|
|
40
|
+
const pushIntervalMs = debug
|
|
41
|
+
? 60 * 1000
|
|
42
|
+
: (config.pushIntervalMinutes ?? 5) * 60 * 1000;
|
|
42
43
|
const hookConfig = {
|
|
43
44
|
gatewayPort: api.config.gateway?.port ?? DEFAULT_GATEWAY_PORT,
|
|
44
45
|
hooksPath: api.config.hooks?.path ?? "/hooks",
|
|
@@ -47,288 +48,12 @@ const molyMemoPlugin = {
|
|
|
47
48
|
api.on("gateway_start", (event) => {
|
|
48
49
|
hookConfig.gatewayPort = event.port;
|
|
49
50
|
});
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
const getMetaPath = (relativePath) => path.join(getDataDir(), relativePath.replace(/\.[^.]+$/, ".meta.json"));
|
|
54
|
-
const getSuggestionsPath = () => path.join(getPluginDir(), "molymemo-suggestions.json");
|
|
55
|
-
const ensureDir = (filePath) => {
|
|
56
|
-
const dir = path.dirname(filePath);
|
|
57
|
-
if (!fs.existsSync(dir))
|
|
58
|
-
fs.mkdirSync(dir, { recursive: true });
|
|
59
|
-
};
|
|
60
|
-
const readMeta = (relativePath) => {
|
|
61
|
-
try {
|
|
62
|
-
const raw = fs.readFileSync(getMetaPath(relativePath), "utf-8");
|
|
63
|
-
return JSON.parse(raw);
|
|
64
|
-
}
|
|
65
|
-
catch {
|
|
66
|
-
return null;
|
|
67
|
-
}
|
|
68
|
-
};
|
|
69
|
-
const writeMeta = (relativePath, meta) => {
|
|
70
|
-
const metaPath = getMetaPath(relativePath);
|
|
71
|
-
ensureDir(metaPath);
|
|
72
|
-
fs.writeFileSync(metaPath, JSON.stringify(meta) + "\n", "utf-8");
|
|
73
|
-
};
|
|
74
|
-
const scanLocalFiles = () => {
|
|
75
|
-
const dataDir = getDataDir();
|
|
76
|
-
if (!fs.existsSync(dataDir)) {
|
|
77
|
-
logger.info(`scanLocalFiles: dataDir not found: ${dataDir}`);
|
|
78
|
-
return [];
|
|
79
|
-
}
|
|
80
|
-
const files = [];
|
|
81
|
-
const scanDir = (dir, prefix) => {
|
|
82
|
-
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
83
|
-
for (const entry of entries) {
|
|
84
|
-
if (entry.isDirectory()) {
|
|
85
|
-
scanDir(path.join(dir, entry.name), `${prefix}${entry.name}/`);
|
|
86
|
-
}
|
|
87
|
-
else if (entry.isFile() &&
|
|
88
|
-
entry.name.endsWith(".meta.json")) {
|
|
89
|
-
const metaPath = `${prefix}${entry.name.replace(/\.meta\.json$/, ".md")}`;
|
|
90
|
-
const meta = readMeta(metaPath);
|
|
91
|
-
if (!meta)
|
|
92
|
-
continue;
|
|
93
|
-
const filePath = meta.path ?? metaPath;
|
|
94
|
-
files.push({
|
|
95
|
-
path: filePath,
|
|
96
|
-
last_sync_at: meta.latest_at ?? "",
|
|
97
|
-
});
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
};
|
|
101
|
-
scanDir(dataDir, "");
|
|
102
|
-
return files;
|
|
103
|
-
};
|
|
104
|
-
// ── Per-session debounce for agent analysis ──
|
|
105
|
-
const sessionTimers = new Map();
|
|
106
|
-
const analysisQueue = [];
|
|
107
|
-
let processingQueue = false;
|
|
108
|
-
const analysisGapMs = debug ? 15_000 : 60_000;
|
|
109
|
-
const triggerAgentAnalysis = async (filePath) => {
|
|
110
|
-
const meta = readMeta(filePath);
|
|
111
|
-
if (meta?.analyzed_at && meta.analyzed_at >= meta.latest_at) {
|
|
112
|
-
logger.info(`Skipping analysis for ${filePath}: already analyzed at ${meta.analyzed_at}`);
|
|
113
|
-
return;
|
|
114
|
-
}
|
|
115
|
-
const dataFilePath = path.join(getDataDir(), filePath);
|
|
116
|
-
const suggestionsPath = getSuggestionsPath();
|
|
117
|
-
const memoryBaseDir = path.join(workspaceDir, "memory", PLUGIN_ID);
|
|
118
|
-
const memoryFilePath = path.join(memoryBaseDir, filePath);
|
|
119
|
-
const message = [
|
|
120
|
-
"You are analyzing an AI chat session file for valuable insights and proactive opportunities.",
|
|
121
|
-
"",
|
|
122
|
-
`Read the file at ${dataFilePath} and analyze the recent conversation content.`,
|
|
123
|
-
"",
|
|
124
|
-
"## Task 1: Long-term Memory Extraction",
|
|
125
|
-
`Write valuable findings as a Markdown file to ${memoryFilePath} (auto-indexed as long-term memory). Create parent directories if needed.`,
|
|
126
|
-
"Focus on: key decisions, learned facts, user preferences, domain knowledge, and recurring patterns.",
|
|
127
|
-
"",
|
|
128
|
-
"## Task 2: Proactive Suggestions",
|
|
129
|
-
`Read the current suggestion list at ${suggestionsPath} (the file may not exist yet — if so, create it). Then update it with new suggestions.`,
|
|
130
|
-
"",
|
|
131
|
-
"Suggestions should focus on what OpenClaw can **proactively do next** for the user, such as:",
|
|
132
|
-
"- Create a specialized Agent Skill based on topics discussed (e.g. a domain-expert skill for a field the user frequently explores)",
|
|
133
|
-
"- Deep-dive research into a topic the user showed interest in but didn't fully explore",
|
|
134
|
-
"- Set up periodic monitoring or reports (e.g. track price changes, news updates, project status)",
|
|
135
|
-
"- Automate a repetitive workflow the user described",
|
|
136
|
-
"- Connect insights across different chat sessions the user has had",
|
|
137
|
-
"- Suggest relevant tools, resources, or next steps based on the conversation context",
|
|
138
|
-
"",
|
|
139
|
-
`Each suggestion entry must have this structure (context is an array — one entry per source session, multiple if the suggestion spans several conversations):`,
|
|
140
|
-
JSON.stringify({
|
|
141
|
-
id: "unique-id (use timestamp + short hash)",
|
|
142
|
-
name: "Short actionable title",
|
|
143
|
-
content: "What OpenClaw can do and why it's valuable (1-3 sentences)",
|
|
144
|
-
context: [
|
|
145
|
-
{
|
|
146
|
-
platform: "Source AI platform name (e.g. ChatGPT, Gemini)",
|
|
147
|
-
sessionPath: `relative path under chat-data/, e.g. ChatGPT/abc123.md (current file: ${filePath})`,
|
|
148
|
-
summary: "2-5 sentence summary of the relevant discussion",
|
|
149
|
-
},
|
|
150
|
-
],
|
|
151
|
-
createdAt: "ISO timestamp",
|
|
152
|
-
pushed: false,
|
|
153
|
-
}, null, 2),
|
|
154
|
-
"",
|
|
155
|
-
`Keep the total number of suggestions at most ${maxSuggestions}. Remove the oldest pushed entries first if the limit is exceeded.`,
|
|
156
|
-
"Avoid duplicate or near-duplicate suggestions.",
|
|
157
|
-
"Only add suggestions that are genuinely actionable by OpenClaw.",
|
|
158
|
-
"",
|
|
159
|
-
"IMPORTANT: Respond with only the single word \"done\" after completing your tasks. Do not summarize, chat, or address the user.",
|
|
160
|
-
].join("\n");
|
|
161
|
-
const ok = await postAgentHook(hookConfig, {
|
|
162
|
-
message,
|
|
163
|
-
name: "MolyMemo-Analyze",
|
|
164
|
-
deliver: false,
|
|
165
|
-
}, logger);
|
|
166
|
-
if (ok) {
|
|
167
|
-
if (meta) {
|
|
168
|
-
meta.analyzed_at = new Date().toISOString();
|
|
169
|
-
writeMeta(filePath, meta);
|
|
170
|
-
}
|
|
171
|
-
logger.info(`Agent analysis triggered for ${filePath}`);
|
|
172
|
-
}
|
|
173
|
-
};
|
|
174
|
-
const enqueueAnalysis = (filePath) => {
|
|
175
|
-
if (!analysisQueue.includes(filePath)) {
|
|
176
|
-
analysisQueue.push(filePath);
|
|
177
|
-
logger.info(`Queued analysis for ${filePath} (queue size: ${analysisQueue.length})`);
|
|
178
|
-
}
|
|
179
|
-
void processAnalysisQueue();
|
|
180
|
-
};
|
|
181
|
-
const processAnalysisQueue = async () => {
|
|
182
|
-
if (processingQueue)
|
|
183
|
-
return;
|
|
184
|
-
processingQueue = true;
|
|
185
|
-
while (analysisQueue.length > 0) {
|
|
186
|
-
const filePath = analysisQueue.shift();
|
|
187
|
-
try {
|
|
188
|
-
await triggerAgentAnalysis(filePath);
|
|
189
|
-
}
|
|
190
|
-
catch (err) {
|
|
191
|
-
logger.error(`Agent analysis error for ${filePath}: ${err}`);
|
|
192
|
-
}
|
|
193
|
-
if (analysisQueue.length > 0) {
|
|
194
|
-
logger.info(`Waiting ${analysisGapMs / 1000}s before next analysis (${analysisQueue.length} remaining)`);
|
|
195
|
-
await new Promise((resolve) => setTimeout(resolve, analysisGapMs));
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
processingQueue = false;
|
|
199
|
-
};
|
|
200
|
-
const resetSessionTimer = (filePath) => {
|
|
201
|
-
const existing = sessionTimers.get(filePath);
|
|
202
|
-
if (existing)
|
|
203
|
-
clearTimeout(existing);
|
|
204
|
-
const timer = setTimeout(() => {
|
|
205
|
-
sessionTimers.delete(filePath);
|
|
206
|
-
enqueueAnalysis(filePath);
|
|
207
|
-
}, sessionIdleMs);
|
|
208
|
-
sessionTimers.set(filePath, timer);
|
|
209
|
-
};
|
|
210
|
-
// ── Push suggestions ──
|
|
211
|
-
let pushTimer = null;
|
|
212
|
-
const resolvePushTargets = async () => {
|
|
213
|
-
const targets = [];
|
|
214
|
-
const channels = api.config.channels ?? {};
|
|
215
|
-
for (const [channelId, channelCfg] of Object.entries(channels)) {
|
|
216
|
-
if (channelCfg?.enabled === false)
|
|
217
|
-
continue;
|
|
218
|
-
try {
|
|
219
|
-
const allowList = await api.runtime.channel.pairing.readAllowFromStore(channelId);
|
|
220
|
-
for (const userId of allowList) {
|
|
221
|
-
targets.push({ channel: channelId, to: userId });
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
catch (err) {
|
|
225
|
-
logger.warn(`Failed to read allowFrom for ${channelId}: ${err}`);
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
return targets;
|
|
229
|
-
};
|
|
230
|
-
const pushSuggestions = async () => {
|
|
231
|
-
if (!hookConfig.hooksToken)
|
|
232
|
-
return;
|
|
233
|
-
const suggestionsPath = getSuggestionsPath();
|
|
234
|
-
const allSuggestions = (() => {
|
|
235
|
-
try {
|
|
236
|
-
const raw = fs.readFileSync(suggestionsPath, "utf-8");
|
|
237
|
-
return JSON.parse(raw);
|
|
238
|
-
}
|
|
239
|
-
catch (e) {
|
|
240
|
-
return `read error: ${e}`;
|
|
241
|
-
}
|
|
242
|
-
})();
|
|
243
|
-
logger.info(`Push check path: ${suggestionsPath} | raw: ${JSON.stringify(allSuggestions).slice(0, 300)}`);
|
|
244
|
-
const unpushed = getUnpushedSuggestions(suggestionsPath);
|
|
245
|
-
if (unpushed.length === 0) {
|
|
246
|
-
logger.info("Push check: no unpushed suggestions");
|
|
247
|
-
return;
|
|
248
|
-
}
|
|
249
|
-
const targets = await resolvePushTargets();
|
|
250
|
-
if (targets.length === 0) {
|
|
251
|
-
logger.info("Push check: no paired users found on any channel");
|
|
252
|
-
return;
|
|
253
|
-
}
|
|
254
|
-
logger.info(`Push check: ${unpushed.length} suggestion(s) → ${targets.length} target(s)`);
|
|
255
|
-
const suggestionsJson = JSON.stringify(unpushed.map((s) => ({
|
|
256
|
-
name: s.name,
|
|
257
|
-
content: s.content,
|
|
258
|
-
sources: (Array.isArray(s.context) ? s.context : [s.context]).map((c) => ({
|
|
259
|
-
platform: c.platform,
|
|
260
|
-
summary: c.summary,
|
|
261
|
-
})),
|
|
262
|
-
})), null, 2);
|
|
263
|
-
const pushMessage = [
|
|
264
|
-
"You are a proactive assistant delivering MolyMemo suggestions to the user.",
|
|
265
|
-
"",
|
|
266
|
-
"MolyMemo has analyzed the user's recent AI chat sessions and generated the following suggestions:",
|
|
267
|
-
"",
|
|
268
|
-
suggestionsJson,
|
|
269
|
-
"",
|
|
270
|
-
"Your task: Inform the user about these suggestions in a concise and natural way.",
|
|
271
|
-
"- Start your message with \"📋 **MolyMemo**\" so the user knows where these suggestions come from",
|
|
272
|
-
"- Present each suggestion clearly with its rationale",
|
|
273
|
-
"- Be brief — no filler, no preamble after the header",
|
|
274
|
-
"- Ask if they'd like you to act on any of them",
|
|
275
|
-
"- Use the user's language/locale if you can infer it from the suggestions",
|
|
276
|
-
].join("\n");
|
|
277
|
-
let anyOk = false;
|
|
278
|
-
for (const target of targets) {
|
|
279
|
-
const ok = await postAgentHook(hookConfig, {
|
|
280
|
-
message: pushMessage,
|
|
281
|
-
name: "MolyMemo-Push",
|
|
282
|
-
deliver: true,
|
|
283
|
-
channel: target.channel,
|
|
284
|
-
to: target.to,
|
|
285
|
-
}, logger);
|
|
286
|
-
if (ok) {
|
|
287
|
-
logger.info(`Pushed to ${target.channel}:${target.to}`);
|
|
288
|
-
anyOk = true;
|
|
289
|
-
}
|
|
290
|
-
}
|
|
291
|
-
if (anyOk) {
|
|
292
|
-
markSuggestionsPushed(suggestionsPath, unpushed.map((s) => s.id));
|
|
293
|
-
logger.info(`Marked ${unpushed.length} suggestion(s) as pushed`);
|
|
294
|
-
}
|
|
295
|
-
};
|
|
296
|
-
// ── File sync ──
|
|
297
|
-
const writeFileData = (msg) => {
|
|
298
|
-
if (msg.mode === "none") {
|
|
299
|
-
logger.info(`No updates for ${msg.path}`);
|
|
300
|
-
return;
|
|
301
|
-
}
|
|
302
|
-
const dataPath = getDataPath(msg.path);
|
|
303
|
-
ensureDir(dataPath);
|
|
304
|
-
if (msg.content) {
|
|
305
|
-
if (msg.mode === "append") {
|
|
306
|
-
fs.appendFileSync(dataPath, msg.content, "utf-8");
|
|
307
|
-
}
|
|
308
|
-
else {
|
|
309
|
-
fs.writeFileSync(dataPath, msg.content, "utf-8");
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
const existingMeta = readMeta(msg.path);
|
|
313
|
-
const meta = {
|
|
314
|
-
path: msg.path,
|
|
315
|
-
latest_at: msg.latest_at && msg.latest_at !== ZERO_TIME
|
|
316
|
-
? msg.latest_at
|
|
317
|
-
: (existingMeta?.latest_at ?? ""),
|
|
318
|
-
};
|
|
319
|
-
if (msg.title)
|
|
320
|
-
meta.title = msg.title;
|
|
321
|
-
else if (existingMeta?.title)
|
|
322
|
-
meta.title = existingMeta.title;
|
|
323
|
-
if (msg.url)
|
|
324
|
-
meta.url = msg.url;
|
|
325
|
-
else if (existingMeta?.url)
|
|
326
|
-
meta.url = existingMeta.url;
|
|
327
|
-
writeMeta(msg.path, meta);
|
|
328
|
-
logger.info(`Synced ${msg.path} [${msg.mode}]`);
|
|
329
|
-
};
|
|
51
|
+
let store = null;
|
|
52
|
+
let analyzer = null;
|
|
53
|
+
let pusher = null;
|
|
330
54
|
let serverClient = null;
|
|
331
55
|
let syncWorker = null;
|
|
56
|
+
let pushTimer = null;
|
|
332
57
|
if (apiKey) {
|
|
333
58
|
serverClient = new MolyMemoServerClient({
|
|
334
59
|
wsUrl: WS_URL,
|
|
@@ -338,60 +63,6 @@ const molyMemoPlugin = {
|
|
|
338
63
|
debug,
|
|
339
64
|
});
|
|
340
65
|
serverClient.setLogger(logger);
|
|
341
|
-
const activeClient = serverClient;
|
|
342
|
-
const pullFileFn = async (filePath) => {
|
|
343
|
-
if (!syncWorker)
|
|
344
|
-
return;
|
|
345
|
-
try {
|
|
346
|
-
const result = await activeClient.pullFile(filePath);
|
|
347
|
-
writeFileData(result);
|
|
348
|
-
syncWorker.onPullComplete(filePath, result.latest_at);
|
|
349
|
-
if (result.mode !== "none") {
|
|
350
|
-
resetSessionTimer(result.path);
|
|
351
|
-
}
|
|
352
|
-
}
|
|
353
|
-
catch (err) {
|
|
354
|
-
logger.error(`Failed to pull ${filePath}: ${err}`);
|
|
355
|
-
syncWorker.onPullFailed(filePath);
|
|
356
|
-
}
|
|
357
|
-
};
|
|
358
|
-
syncWorker = new SyncWorker((filePath) => {
|
|
359
|
-
void pullFileFn(filePath);
|
|
360
|
-
});
|
|
361
|
-
syncWorker.setLogger(logger);
|
|
362
|
-
activeClient.setHandlers({
|
|
363
|
-
onConnected: async () => {
|
|
364
|
-
try {
|
|
365
|
-
const files = scanLocalFiles();
|
|
366
|
-
for (const f of files) {
|
|
367
|
-
syncWorker?.setSyncedTimestamp(f.path, f.last_sync_at);
|
|
368
|
-
}
|
|
369
|
-
let pendingAnalysis = 0;
|
|
370
|
-
for (const f of files) {
|
|
371
|
-
const meta = readMeta(f.path);
|
|
372
|
-
if (meta && (!meta.analyzed_at || meta.analyzed_at < meta.latest_at)) {
|
|
373
|
-
enqueueAnalysis(f.path);
|
|
374
|
-
pendingAnalysis++;
|
|
375
|
-
}
|
|
376
|
-
}
|
|
377
|
-
if (pendingAnalysis > 0) {
|
|
378
|
-
logger.info(`${pendingAnalysis} file(s) pending analysis, processing sequentially`);
|
|
379
|
-
}
|
|
380
|
-
logger.info(`Checking updates with ${files.length} local files`);
|
|
381
|
-
const updates = await activeClient.checkUpdates(files);
|
|
382
|
-
logger.info(`${updates.length} files need updating`);
|
|
383
|
-
for (const u of updates)
|
|
384
|
-
syncWorker?.queueSync(u.path, u.latest_at);
|
|
385
|
-
}
|
|
386
|
-
catch (err) {
|
|
387
|
-
logger.error(`Failed to check updates: ${err}`);
|
|
388
|
-
}
|
|
389
|
-
},
|
|
390
|
-
onFileUpdated: (msg) => {
|
|
391
|
-
logger.info(`File updated: ${msg.path} at ${msg.latest_at}`);
|
|
392
|
-
syncWorker?.queueSync(msg.path, msg.latest_at);
|
|
393
|
-
},
|
|
394
|
-
});
|
|
395
66
|
}
|
|
396
67
|
api.registerTool({
|
|
397
68
|
name: "molymemo_browser_history",
|
|
@@ -433,18 +104,81 @@ const molyMemoPlugin = {
|
|
|
433
104
|
wsUrl: WS_URL,
|
|
434
105
|
apiUrl: API_URL,
|
|
435
106
|
connected: serverClient?.isConnected() ?? false,
|
|
436
|
-
pluginDir: getPluginDir(),
|
|
437
|
-
dataDir: getDataDir(),
|
|
107
|
+
pluginDir: store?.getPluginDir() ?? "",
|
|
108
|
+
dataDir: store?.getDataDir() ?? "",
|
|
438
109
|
});
|
|
439
110
|
});
|
|
440
111
|
api.registerService({
|
|
441
112
|
id: PLUGIN_ID,
|
|
442
113
|
start: async (ctx) => {
|
|
443
|
-
workspaceDir = ctx.workspaceDir ?? "";
|
|
114
|
+
const workspaceDir = ctx.workspaceDir ?? "";
|
|
444
115
|
if (!serverClient) {
|
|
445
116
|
logger.warn('MolyMemo: missing apiKey. Set plugins.entries.molymemo.config.apiKey or env "MOLYMEMO_API_KEY".');
|
|
446
117
|
return;
|
|
447
118
|
}
|
|
119
|
+
store = new ChatStore(workspaceDir, PLUGIN_ID, logger);
|
|
120
|
+
analyzer = new Analyzer({
|
|
121
|
+
workspaceDir,
|
|
122
|
+
pluginId: PLUGIN_ID,
|
|
123
|
+
maxSuggestions,
|
|
124
|
+
sessionIdleMs,
|
|
125
|
+
analysisGapMs: debug ? 15_000 : 60_000,
|
|
126
|
+
}, hookConfig, store, logger);
|
|
127
|
+
pusher = new SuggestionPusher(hookConfig, store.getSuggestionsPath(), api, logger);
|
|
128
|
+
const activeClient = serverClient;
|
|
129
|
+
syncWorker = new SyncWorker(async (filePath) => {
|
|
130
|
+
if (!syncWorker || !store || !analyzer)
|
|
131
|
+
return;
|
|
132
|
+
try {
|
|
133
|
+
const result = await activeClient.pullFile(filePath);
|
|
134
|
+
store.writeFileData(result);
|
|
135
|
+
syncWorker.onPullComplete(filePath, result.latest_at);
|
|
136
|
+
if (result.mode !== "none") {
|
|
137
|
+
analyzer.resetSessionTimer(result.path);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
catch (err) {
|
|
141
|
+
logger.error(`Failed to pull ${filePath}: ${err}`);
|
|
142
|
+
syncWorker.onPullFailed(filePath);
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
syncWorker.setLogger(logger);
|
|
146
|
+
activeClient.setHandlers({
|
|
147
|
+
onConnected: async () => {
|
|
148
|
+
if (!store || !syncWorker || !analyzer)
|
|
149
|
+
return;
|
|
150
|
+
try {
|
|
151
|
+
const files = store.scanLocalFiles();
|
|
152
|
+
for (const f of files) {
|
|
153
|
+
syncWorker.setSyncedTimestamp(f.path, f.last_sync_at);
|
|
154
|
+
}
|
|
155
|
+
let pendingAnalysis = 0;
|
|
156
|
+
for (const f of files) {
|
|
157
|
+
const meta = store.readMeta(f.path);
|
|
158
|
+
if (meta &&
|
|
159
|
+
(!meta.analyzed_at || meta.analyzed_at < meta.latest_at)) {
|
|
160
|
+
analyzer.enqueueAnalysis(f.path);
|
|
161
|
+
pendingAnalysis++;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
if (pendingAnalysis > 0) {
|
|
165
|
+
logger.info(`${pendingAnalysis} file(s) pending analysis, processing sequentially`);
|
|
166
|
+
}
|
|
167
|
+
logger.info(`Checking updates with ${files.length} local files`);
|
|
168
|
+
const updates = await activeClient.checkUpdates(files);
|
|
169
|
+
logger.info(`${updates.length} files need updating`);
|
|
170
|
+
for (const u of updates)
|
|
171
|
+
syncWorker.queueSync(u.path, u.latest_at);
|
|
172
|
+
}
|
|
173
|
+
catch (err) {
|
|
174
|
+
logger.error(`Failed to check updates: ${err}`);
|
|
175
|
+
}
|
|
176
|
+
},
|
|
177
|
+
onFileUpdated: (msg) => {
|
|
178
|
+
logger.info(`File updated: ${msg.path} at ${msg.latest_at}`);
|
|
179
|
+
syncWorker?.queueSync(msg.path, msg.latest_at);
|
|
180
|
+
},
|
|
181
|
+
});
|
|
448
182
|
logger.info(`MolyMemo service starting, workspace: ${workspaceDir}`);
|
|
449
183
|
const connected = await serverClient.connect();
|
|
450
184
|
if (connected) {
|
|
@@ -454,7 +188,7 @@ const molyMemoPlugin = {
|
|
|
454
188
|
logger.warn("Failed to connect, will retry...");
|
|
455
189
|
}
|
|
456
190
|
pushTimer = setInterval(() => {
|
|
457
|
-
|
|
191
|
+
pusher?.push().catch((err) => logger.error(`Push error: ${err}`));
|
|
458
192
|
}, pushIntervalMs);
|
|
459
193
|
logger.info(`Push timer started (interval: ${pushIntervalMs / 1000}s)`);
|
|
460
194
|
},
|
|
@@ -464,10 +198,7 @@ const molyMemoPlugin = {
|
|
|
464
198
|
clearInterval(pushTimer);
|
|
465
199
|
pushTimer = null;
|
|
466
200
|
}
|
|
467
|
-
|
|
468
|
-
clearTimeout(timer);
|
|
469
|
-
}
|
|
470
|
-
sessionTimers.clear();
|
|
201
|
+
analyzer?.clearTimers();
|
|
471
202
|
await serverClient?.disconnect();
|
|
472
203
|
},
|
|
473
204
|
});
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAEzC,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAGzD,MAAM,SAAS,GAAG,UAAU,CAAC;AAC7B,MAAM,MAAM,GACV,8DAA8D,CAAC;AACjE,MAAM,OAAO,GAAG,yCAAyC,CAAC;AAC1D,MAAM,qBAAqB,GAAG,IAAI,CAAC;AACnC,MAAM,oBAAoB,GAAG,KAAK,CAAC;AAEnC,MAAM,YAAY,GAAG,CAAC;KACnB,MAAM,CAAC;IACN,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;IACpC,KAAK,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;IAC7B,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;IAClD,mBAAmB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;IACvD,kBAAkB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;CACvD,CAAC;KACD,MAAM,EAAE,CAAC;AAIZ,MAAM,cAAc,GAAG;IACrB,EAAE,EAAE,SAAS;IACb,IAAI,EAAE,UAAU;IAChB,WAAW,EAAE,4CAA4C;IACzD,YAAY;IAEZ,QAAQ,CAAC,GAAsB;QAC7B,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC;QAC1B,MAAM,MAAM,GAAG,YAAY,CAAC,SAAS,CAAC,GAAG,CAAC,YAAY,IAAI,EAAE,CAAC,CAAC;QAC9D,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpB,MAAM,CAAC,IAAI,CAAC,iCAAiC,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;QACvE,CAAC;QAED,MAAM,MAAM,GAAiB,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;QAC/D,MAAM,MAAM,GAAG,CAAC,MAAM,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QAC5C,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,IAAI,KAAK,CAAC;QACpC,MAAM,cAAc,GAAG,MAAM,CAAC,cAAc,IAAI,EAAE,CAAC;QACnD,MAAM,aAAa,GAAG,KAAK;YACzB,CAAC,CAAC,EAAE,GAAG,IAAI;YACX,CAAC,CAAC,CAAC,MAAM,CAAC,kBAAkB,IAAI,CAAC,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;QACjD,MAAM,cAAc,GAAG,KAAK;YAC1B,CAAC,CAAC,EAAE,GAAG,IAAI;YACX,CAAC,CAAC,CAAC,MAAM,CAAC,mBAAmB,IAAI,CAAC,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;QAElD,MAAM,UAAU,GAAqB;YACnC,WAAW,EAAE,GAAG,CAAC,MAAM,CAAC,OAAO,EAAE,IAAI,IAAI,oBAAoB;YAC7D,SAAS,EAAE,GAAG,CAAC,MAAM,CAAC,KAAK,EAAE,IAAI,IAAI,QAAQ;YAC7C,UAAU,EAAE,GAAG,CAAC,MAAM,CAAC,KAAK,EAAE,KAAK,IAAI,EAAE;SAC1C,CAAC;QAEF,GAAG,CAAC,EAAE,CAAC,eAAe,EAAE,CAAC,KAAK,EAAE,EAAE;YAChC,UAAU,CAAC,WAAW,GAAG,KAAK,CAAC,IAAI,CAAC;QACtC,CAAC,CAAC,CAAC;QAEH,IAAI,KAAK,GAAqB,IAAI,CAAC;QACnC,IAAI,QAAQ,GAAoB,IAAI,CAAC;QACrC,IAAI,MAAM,GAA4B,IAAI,CAAC;QAC3C,IAAI,YAAY,GAAgC,IAAI,CAAC;QACrD,IAAI,UAAU,GAAsB,IAAI,CAAC;QACzC,IAAI,SAAS,GAA0C,IAAI,CAAC;QAE5D,IAAI,MAAM,EAAE,CAAC;YACX,YAAY,GAAG,IAAI,oBAAoB,CAAC;gBACtC,KAAK,EAAE,MAAM;gBACb,MAAM,EAAE,OAAO;gBACf,MAAM;gBACN,iBAAiB,EAAE,qBAAqB;gBACxC,KAAK;aACN,CAAC,CAAC;YACH,YAAY,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;QACjC,CAAC;QAED,GAAG,CAAC,YAAY,CAAC;YACf,IAAI,EAAE,0BAA0B;YAChC,KAAK,EAAE,iBAAiB;YACxB,WAAW,EACT,6IAA6I;YAC/I,UAAU,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;YAC3B,KAAK,CAAC,OAAO;gBACX,IAAI,CAAC;oBACH,IAAI,CAAC,YAAY,EAAE,CAAC;wBAClB,OAAO;4BACL,OAAO,EAAE;gCACP;oCACE,IAAI,EAAE,MAAe;oCACrB,IAAI,EAAE,oGAAoG;iCAC3G;6BACF;4BACD,OAAO,EAAE,EAAE;yBACZ,CAAC;oBACJ,CAAC;oBACD,MAAM,KAAK,GAAG,MAAM,YAAY,CAAC,mBAAmB,EAAE,CAAC;oBACvD,MAAM,IAAI,GACR,KAAK,CAAC,MAAM,GAAG,CAAC;wBACd,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;wBAChC,CAAC,CAAC,2BAA2B,CAAC;oBAClC,OAAO;wBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,CAAC;wBAC1C,OAAO,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,MAAM,EAAE;qBACjC,CAAC;gBACJ,CAAC;gBAAC,OAAO,GAAG,EAAE,CAAC;oBACb,OAAO;wBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,UAAU,GAAG,EAAE,EAAE,CAAC;wBAC3D,OAAO,EAAE,EAAE;qBACZ,CAAC;gBACJ,CAAC;YACH,CAAC;SACF,CAAC,CAAC;QAEH,GAAG,CAAC,qBAAqB,CAAC,iBAAiB,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE;YACjE,OAAO,CAAC,IAAI,EAAE;gBACZ,KAAK,EAAE,MAAM;gBACb,MAAM,EAAE,OAAO;gBACf,SAAS,EAAE,YAAY,EAAE,WAAW,EAAE,IAAI,KAAK;gBAC/C,SAAS,EAAE,KAAK,EAAE,YAAY,EAAE,IAAI,EAAE;gBACtC,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE;aACnC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,GAAG,CAAC,eAAe,CAAC;YAClB,EAAE,EAAE,SAAS;YACb,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;gBACnB,MAAM,YAAY,GAAG,GAAG,CAAC,YAAY,IAAI,EAAE,CAAC;gBAE5C,IAAI,CAAC,YAAY,EAAE,CAAC;oBAClB,MAAM,CAAC,IAAI,CACT,iGAAiG,CAClG,CAAC;oBACF,OAAO;gBACT,CAAC;gBAED,KAAK,GAAG,IAAI,SAAS,CAAC,YAAY,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC;gBACvD,QAAQ,GAAG,IAAI,QAAQ,CACrB;oBACE,YAAY;oBACZ,QAAQ,EAAE,SAAS;oBACnB,cAAc;oBACd,aAAa;oBACb,aAAa,EAAE,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM;iBACvC,EACD,UAAU,EACV,KAAK,EACL,MAAM,CACP,CAAC;gBACF,MAAM,GAAG,IAAI,gBAAgB,CAC3B,UAAU,EACV,KAAK,CAAC,kBAAkB,EAAE,EAC1B,GAAG,EACH,MAAM,CACP,CAAC;gBAEF,MAAM,YAAY,GAAG,YAAY,CAAC;gBAClC,UAAU,GAAG,IAAI,UAAU,CAAC,KAAK,EAAE,QAAQ,EAAE,EAAE;oBAC7C,IAAI,CAAC,UAAU,IAAI,CAAC,KAAK,IAAI,CAAC,QAAQ;wBAAE,OAAO;oBAC/C,IAAI,CAAC;wBACH,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;wBACrD,KAAK,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;wBAC5B,UAAU,CAAC,cAAc,CAAC,QAAQ,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC;wBACtD,IAAI,MAAM,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;4BAC3B,QAAQ,CAAC,iBAAiB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;wBAC1C,CAAC;oBACH,CAAC;oBAAC,OAAO,GAAG,EAAE,CAAC;wBACb,MAAM,CAAC,KAAK,CAAC,kBAAkB,QAAQ,KAAK,GAAG,EAAE,CAAC,CAAC;wBACnD,UAAU,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;oBACpC,CAAC;gBACH,CAAC,CAAC,CAAC;gBACH,UAAU,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;gBAE7B,YAAY,CAAC,WAAW,CAAC;oBACvB,WAAW,EAAE,KAAK,IAAI,EAAE;wBACtB,IAAI,CAAC,KAAK,IAAI,CAAC,UAAU,IAAI,CAAC,QAAQ;4BAAE,OAAO;wBAC/C,IAAI,CAAC;4BACH,MAAM,KAAK,GAAG,KAAK,CAAC,cAAc,EAAE,CAAC;4BACrC,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;gCACtB,UAAU,CAAC,kBAAkB,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,YAAY,CAAC,CAAC;4BACxD,CAAC;4BAED,IAAI,eAAe,GAAG,CAAC,CAAC;4BACxB,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;gCACtB,MAAM,IAAI,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;gCACpC,IACE,IAAI;oCACJ,CAAC,CAAC,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,SAAS,CAAC,EACxD,CAAC;oCACD,QAAQ,CAAC,eAAe,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;oCACjC,eAAe,EAAE,CAAC;gCACpB,CAAC;4BACH,CAAC;4BACD,IAAI,eAAe,GAAG,CAAC,EAAE,CAAC;gCACxB,MAAM,CAAC,IAAI,CACT,GAAG,eAAe,oDAAoD,CACvE,CAAC;4BACJ,CAAC;4BAED,MAAM,CAAC,IAAI,CAAC,yBAAyB,KAAK,CAAC,MAAM,cAAc,CAAC,CAAC;4BACjE,MAAM,OAAO,GAAG,MAAM,YAAY,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;4BACvD,MAAM,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,MAAM,sBAAsB,CAAC,CAAC;4BACrD,KAAK,MAAM,CAAC,IAAI,OAAO;gCAAE,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC;wBACrE,CAAC;wBAAC,OAAO,GAAG,EAAE,CAAC;4BACb,MAAM,CAAC,KAAK,CAAC,4BAA4B,GAAG,EAAE,CAAC,CAAC;wBAClD,CAAC;oBACH,CAAC;oBAED,aAAa,EAAE,CAAC,GAAG,EAAE,EAAE;wBACrB,MAAM,CAAC,IAAI,CAAC,iBAAiB,GAAG,CAAC,IAAI,OAAO,GAAG,CAAC,SAAS,EAAE,CAAC,CAAC;wBAC7D,UAAU,EAAE,SAAS,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,SAAS,CAAC,CAAC;oBACjD,CAAC;iBACF,CAAC,CAAC;gBAEH,MAAM,CAAC,IAAI,CAAC,yCAAyC,YAAY,EAAE,CAAC,CAAC;gBACrE,MAAM,SAAS,GAAG,MAAM,YAAY,CAAC,OAAO,EAAE,CAAC;gBAC/C,IAAI,SAAS,EAAE,CAAC;oBACd,MAAM,CAAC,IAAI,CAAC,8BAA8B,CAAC,CAAC;gBAC9C,CAAC;qBAAM,CAAC;oBACN,MAAM,CAAC,IAAI,CAAC,kCAAkC,CAAC,CAAC;gBAClD,CAAC;gBAED,SAAS,GAAG,WAAW,CAAC,GAAG,EAAE;oBAC3B,MAAM,EAAE,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,eAAe,GAAG,EAAE,CAAC,CAAC,CAAC;gBACpE,CAAC,EAAE,cAAc,CAAC,CAAC;gBACnB,MAAM,CAAC,IAAI,CAAC,iCAAiC,cAAc,GAAG,IAAI,IAAI,CAAC,CAAC;YAC1E,CAAC;YAED,IAAI,EAAE,KAAK,IAAI,EAAE;gBACf,MAAM,CAAC,IAAI,CAAC,8BAA8B,CAAC,CAAC;gBAE5C,IAAI,SAAS,EAAE,CAAC;oBACd,aAAa,CAAC,SAAS,CAAC,CAAC;oBACzB,SAAS,GAAG,IAAI,CAAC;gBACnB,CAAC;gBAED,QAAQ,EAAE,WAAW,EAAE,CAAC;gBACxB,MAAM,YAAY,EAAE,UAAU,EAAE,CAAC;YACnC,CAAC;SACF,CAAC,CAAC;IACL,CAAC;CACF,CAAC;AAEF,eAAe,cAAc,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { PluginLogger } from "./server-client.js";
|
|
2
|
+
import type { HookClientConfig } from "./hook-client.js";
|
|
3
|
+
import type { OpenClawPluginApi } from "openclaw/plugin-sdk";
|
|
4
|
+
export declare class SuggestionPusher {
|
|
5
|
+
private hookConfig;
|
|
6
|
+
private suggestionsPath;
|
|
7
|
+
private api;
|
|
8
|
+
private logger;
|
|
9
|
+
constructor(hookConfig: HookClientConfig, suggestionsPath: string, api: OpenClawPluginApi, logger: PluginLogger);
|
|
10
|
+
push(): Promise<void>;
|
|
11
|
+
private resolvePushTargets;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=push-suggestions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"push-suggestions.d.ts","sourceRoot":"","sources":["../src/push-suggestions.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAGzD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAE7D,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,UAAU,CAAmB;IACrC,OAAO,CAAC,eAAe,CAAS;IAChC,OAAO,CAAC,GAAG,CAAoB;IAC/B,OAAO,CAAC,MAAM,CAAe;gBAG3B,UAAU,EAAE,gBAAgB,EAC5B,eAAe,EAAE,MAAM,EACvB,GAAG,EAAE,iBAAiB,EACtB,MAAM,EAAE,YAAY;IAQhB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;YAqFb,kBAAkB;CAqBjC"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import * as fs from "node:fs";
|
|
2
|
+
import { postAgentHook } from "./hook-client.js";
|
|
3
|
+
import { getUnpushedSuggestions, markSuggestionsPushed } from "./suggestions.js";
|
|
4
|
+
export class SuggestionPusher {
|
|
5
|
+
hookConfig;
|
|
6
|
+
suggestionsPath;
|
|
7
|
+
api;
|
|
8
|
+
logger;
|
|
9
|
+
constructor(hookConfig, suggestionsPath, api, logger) {
|
|
10
|
+
this.hookConfig = hookConfig;
|
|
11
|
+
this.suggestionsPath = suggestionsPath;
|
|
12
|
+
this.api = api;
|
|
13
|
+
this.logger = logger;
|
|
14
|
+
}
|
|
15
|
+
async push() {
|
|
16
|
+
if (!this.hookConfig.hooksToken)
|
|
17
|
+
return;
|
|
18
|
+
const allSuggestions = (() => {
|
|
19
|
+
try {
|
|
20
|
+
const raw = fs.readFileSync(this.suggestionsPath, "utf-8");
|
|
21
|
+
return JSON.parse(raw);
|
|
22
|
+
}
|
|
23
|
+
catch (e) {
|
|
24
|
+
return `read error: ${e}`;
|
|
25
|
+
}
|
|
26
|
+
})();
|
|
27
|
+
this.logger.info(`Push check path: ${this.suggestionsPath} | raw: ${JSON.stringify(allSuggestions).slice(0, 300)}`);
|
|
28
|
+
const unpushed = getUnpushedSuggestions(this.suggestionsPath);
|
|
29
|
+
if (unpushed.length === 0) {
|
|
30
|
+
this.logger.info("Push check: no unpushed suggestions");
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
const targets = await this.resolvePushTargets();
|
|
34
|
+
if (targets.length === 0) {
|
|
35
|
+
this.logger.info("Push check: no paired users found on any channel");
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
this.logger.info(`Push check: ${unpushed.length} suggestion(s) → ${targets.length} target(s)`);
|
|
39
|
+
const suggestionsJson = JSON.stringify(unpushed.map((s) => ({
|
|
40
|
+
name: s.name,
|
|
41
|
+
content: s.content,
|
|
42
|
+
sources: (Array.isArray(s.context) ? s.context : [s.context]).map((c) => ({ platform: c.platform, summary: c.summary })),
|
|
43
|
+
})), null, 2);
|
|
44
|
+
const pushMessage = [
|
|
45
|
+
"You are a proactive assistant delivering MolyMemo suggestions to the user.",
|
|
46
|
+
"",
|
|
47
|
+
"MolyMemo has analyzed the user's recent AI chat sessions and generated the following suggestions:",
|
|
48
|
+
"",
|
|
49
|
+
suggestionsJson,
|
|
50
|
+
"",
|
|
51
|
+
"Your task: Inform the user about these suggestions in a concise and natural way.",
|
|
52
|
+
"- Start your message with \"📋 **MolyMemo**\" so the user knows where these suggestions come from",
|
|
53
|
+
"- Present each suggestion clearly with its rationale",
|
|
54
|
+
"- Be brief — no filler, no preamble after the header",
|
|
55
|
+
"- Ask if they'd like you to act on any of them",
|
|
56
|
+
"- Use the user's language/locale if you can infer it from the suggestions",
|
|
57
|
+
].join("\n");
|
|
58
|
+
let anyOk = false;
|
|
59
|
+
for (const target of targets) {
|
|
60
|
+
const ok = await postAgentHook(this.hookConfig, {
|
|
61
|
+
message: pushMessage,
|
|
62
|
+
name: "MolyMemo-Push",
|
|
63
|
+
deliver: true,
|
|
64
|
+
channel: target.channel,
|
|
65
|
+
to: target.to,
|
|
66
|
+
}, this.logger);
|
|
67
|
+
if (ok) {
|
|
68
|
+
this.logger.info(`Pushed to ${target.channel}:${target.to}`);
|
|
69
|
+
anyOk = true;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
if (anyOk) {
|
|
73
|
+
markSuggestionsPushed(this.suggestionsPath, unpushed.map((s) => s.id));
|
|
74
|
+
this.logger.info(`Marked ${unpushed.length} suggestion(s) as pushed`);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
async resolvePushTargets() {
|
|
78
|
+
const targets = [];
|
|
79
|
+
const channels = this.api.config.channels ?? {};
|
|
80
|
+
for (const [channelId, channelCfg] of Object.entries(channels)) {
|
|
81
|
+
if (channelCfg?.enabled === false)
|
|
82
|
+
continue;
|
|
83
|
+
try {
|
|
84
|
+
const allowList = await this.api.runtime.channel.pairing.readAllowFromStore(channelId);
|
|
85
|
+
for (const userId of allowList) {
|
|
86
|
+
targets.push({ channel: channelId, to: userId });
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
catch (err) {
|
|
90
|
+
this.logger.warn(`Failed to read allowFrom for ${channelId}: ${err}`);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
return targets;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=push-suggestions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"push-suggestions.js","sourceRoot":"","sources":["../src/push-suggestions.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: molymemo-suggestions
|
|
3
|
+
description: "REQUIRED when you see 'MolyMemo' anywhere — in system messages, user messages, or events. Do NOT respond based on system message text alone. Always read molymemo/molymemo-suggestions.json first to get full context."
|
|
4
|
+
globs:
|
|
5
|
+
- "molymemo/molymemo-suggestions.json"
|
|
6
|
+
- "molymemo/chat-data/**"
|
|
7
|
+
- "memory/molymemo/**"
|
|
8
|
+
alwaysApply: true
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# MolyMemo Suggestions Skill
|
|
12
|
+
|
|
13
|
+
MolyMemo syncs the user's AI chat sessions (ChatGPT, Gemini, DeepSeek, etc.) and generates proactive suggestions for what OpenClaw can do next.
|
|
14
|
+
|
|
15
|
+
## Critical Rule
|
|
16
|
+
|
|
17
|
+
**When you see "MolyMemo" in any system message or event:**
|
|
18
|
+
- ❌ Do NOT summarize or reformat the system message text
|
|
19
|
+
- ✅ ALWAYS read `molymemo/molymemo-suggestions.json` to get the actual suggestions and context
|
|
20
|
+
- ✅ ALWAYS use `context[].summary` and optionally `molymemo/chat-data/{context[].sessionPath}` as your source
|
|
21
|
+
|
|
22
|
+
The system message is just a trigger notification — the real data is in the files.
|
|
23
|
+
|
|
24
|
+
## Delivering Suggestions
|
|
25
|
+
|
|
26
|
+
1. Read `molymemo/molymemo-suggestions.json` — find entries where `pushed: false`
|
|
27
|
+
2. For each suggestion, use `context[].summary` to understand the background
|
|
28
|
+
3. If more detail is needed, read `molymemo/chat-data/{context[].sessionPath}`
|
|
29
|
+
4. Present with "📋 **MolyMemo**" header, grounded in the actual conversation context
|
|
30
|
+
5. Ask if the user wants to act on any of them
|
|
31
|
+
|
|
32
|
+
## Acting on a Suggestion
|
|
33
|
+
|
|
34
|
+
1. Match by name/topic in `molymemo/molymemo-suggestions.json`
|
|
35
|
+
2. Use `context[].summary` as primary source; read full session file if needed
|
|
36
|
+
3. Use `memory_search` for related insights from `memory/molymemo/`
|