@nowledge/openclaw-nowledge-mem 0.3.0 → 0.6.5

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.
@@ -0,0 +1,106 @@
1
+ export function createThreadFetchTool(client, logger) {
2
+ return {
3
+ name: "nowledge_mem_thread_fetch",
4
+ description:
5
+ "Fetch full messages from a conversation thread. Use to read the complete context " +
6
+ "around a memory — pass the sourceThreadId from memory_search or memory_get results, " +
7
+ "or a threadId from nowledge_mem_thread_search. " +
8
+ "Supports pagination for long conversations: set offset to skip earlier messages. " +
9
+ "Useful for progressive retrieval — fetch the first page, then request more if needed.",
10
+ parameters: {
11
+ type: "object",
12
+ properties: {
13
+ threadId: {
14
+ type: "string",
15
+ description:
16
+ "Thread ID from nowledge_mem_thread_search, or sourceThreadId from memory_search / memory_get results",
17
+ },
18
+ offset: {
19
+ type: "number",
20
+ description: "Skip first N messages (for pagination, default 0)",
21
+ },
22
+ limit: {
23
+ type: "number",
24
+ description: "Max messages to return (1-200, default 50)",
25
+ },
26
+ },
27
+ required: ["threadId"],
28
+ },
29
+ async execute(_toolCallId, params) {
30
+ const safeParams = params && typeof params === "object" ? params : {};
31
+ const threadId = String(safeParams.threadId ?? "").trim();
32
+ const offset = Math.max(
33
+ 0,
34
+ Math.trunc(Number(safeParams.offset ?? 0) || 0),
35
+ );
36
+ const limit = Math.min(
37
+ 200,
38
+ Math.max(1, Math.trunc(Number(safeParams.limit ?? 50) || 50)),
39
+ );
40
+
41
+ if (!threadId) {
42
+ return {
43
+ content: [
44
+ {
45
+ type: "text",
46
+ text: JSON.stringify({
47
+ threadId: "",
48
+ error: "threadId is required",
49
+ }),
50
+ },
51
+ ],
52
+ };
53
+ }
54
+
55
+ try {
56
+ const thread = await client.fetchThread(threadId, {
57
+ offset,
58
+ limit,
59
+ });
60
+
61
+ const hasMore =
62
+ thread.messageCount > 0 &&
63
+ offset + thread.messages.length < thread.messageCount;
64
+
65
+ const result = {
66
+ threadId: thread.threadId,
67
+ title: thread.title,
68
+ source: thread.source,
69
+ totalMessages: thread.messageCount,
70
+ offset,
71
+ limit,
72
+ returnedMessages: thread.messages.length,
73
+ hasMore,
74
+ messages: thread.messages,
75
+ };
76
+
77
+ return {
78
+ content: [
79
+ {
80
+ type: "text",
81
+ text: JSON.stringify(result, null, 2),
82
+ },
83
+ ],
84
+ details: {
85
+ threadId: thread.threadId,
86
+ messageCount: thread.messages.length,
87
+ },
88
+ };
89
+ } catch (err) {
90
+ const message = err instanceof Error ? err.message : String(err);
91
+ logger.error(`nowledge_mem_thread_fetch failed: ${message}`);
92
+ return {
93
+ content: [
94
+ {
95
+ type: "text",
96
+ text: JSON.stringify({
97
+ threadId,
98
+ error: message,
99
+ }),
100
+ },
101
+ ],
102
+ };
103
+ }
104
+ },
105
+ };
106
+ }
@@ -0,0 +1,108 @@
1
+ function truncateSnippet(text, maxChars = 400) {
2
+ const value = String(text || "").trim();
3
+ if (!value) return "";
4
+ if (value.length <= maxChars) return value;
5
+ return `${value.slice(0, maxChars)}…`;
6
+ }
7
+
8
+ export function createThreadSearchTool(client, logger) {
9
+ return {
10
+ name: "nowledge_mem_thread_search",
11
+ description:
12
+ "Search past conversations by keyword. Use when the user asks about a past discussion, " +
13
+ "wants to find a conversation from a specific time, or when you want to explore the full context " +
14
+ "around a topic beyond what memory_search returned. " +
15
+ "Returns matched threads with message snippets and relevance scores. " +
16
+ "To read full messages from a thread, pass its threadId to nowledge_mem_thread_fetch.",
17
+ parameters: {
18
+ type: "object",
19
+ properties: {
20
+ query: {
21
+ type: "string",
22
+ description: "Search keywords or natural language query",
23
+ },
24
+ limit: {
25
+ type: "number",
26
+ description: "Max threads to return (1-20, default 5)",
27
+ },
28
+ source: {
29
+ type: "string",
30
+ description:
31
+ "Filter by source platform (e.g. 'openclaw', 'claude-code'). Omit to search all sources.",
32
+ },
33
+ },
34
+ required: ["query"],
35
+ },
36
+ async execute(_toolCallId, params) {
37
+ const safeParams = params && typeof params === "object" ? params : {};
38
+ const query = String(safeParams.query ?? "").trim();
39
+ const limit = Math.min(
40
+ 20,
41
+ Math.max(1, Math.trunc(Number(safeParams.limit ?? 5) || 5)),
42
+ );
43
+ const rawSource = safeParams.source
44
+ ? String(safeParams.source).trim()
45
+ : "";
46
+ const source = rawSource || undefined;
47
+
48
+ if (!query) {
49
+ return {
50
+ content: [
51
+ {
52
+ type: "text",
53
+ text: JSON.stringify({ threads: [], totalFound: 0 }),
54
+ },
55
+ ],
56
+ };
57
+ }
58
+
59
+ try {
60
+ const { threads, totalFound } = await client.searchThreadsFull(query, {
61
+ limit,
62
+ source,
63
+ });
64
+
65
+ const results = threads.map((t) => {
66
+ const msgs = (t.matched_messages ?? []).slice(0, 3);
67
+ return {
68
+ threadId: t.thread_id ?? t.id,
69
+ title: t.title || "(untitled thread)",
70
+ source: t.source ?? "unknown",
71
+ messageCount: Number(t.message_count ?? 0),
72
+ lastActivity: t.last_activity ?? null,
73
+ relevanceScore: Number(t.relevance_score ?? 0),
74
+ matchedMessages: msgs.map((m) => ({
75
+ role: m.role,
76
+ snippet: truncateSnippet(m.snippet),
77
+ })),
78
+ };
79
+ });
80
+
81
+ return {
82
+ content: [
83
+ {
84
+ type: "text",
85
+ text: JSON.stringify({ threads: results, totalFound }, null, 2),
86
+ },
87
+ ],
88
+ details: { query, threadCount: results.length },
89
+ };
90
+ } catch (err) {
91
+ const message = err instanceof Error ? err.message : String(err);
92
+ logger.error(`nowledge_mem_thread_search failed: ${message}`);
93
+ return {
94
+ content: [
95
+ {
96
+ type: "text",
97
+ text: JSON.stringify({
98
+ threads: [],
99
+ totalFound: 0,
100
+ error: message,
101
+ }),
102
+ },
103
+ ],
104
+ };
105
+ }
106
+ },
107
+ };
108
+ }