openclawdreams 3.0.6 → 3.0.7
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/CHANGELOG.md +13 -0
- package/dist/bin/openclawdreams.d.ts +3 -0
- package/dist/bin/openclawdreams.d.ts.map +1 -0
- package/dist/bin/openclawdreams.js +4 -0
- package/dist/bin/openclawdreams.js.map +1 -0
- package/dist/src/backfill.d.ts +2 -0
- package/dist/src/backfill.d.ts.map +1 -0
- package/dist/src/backfill.js +63 -0
- package/dist/src/backfill.js.map +1 -0
- package/dist/src/budget.d.ts +28 -0
- package/dist/src/budget.d.ts.map +1 -0
- package/dist/src/budget.js +117 -0
- package/dist/src/budget.js.map +1 -0
- package/dist/src/cli.d.ts +19 -0
- package/dist/src/cli.d.ts.map +1 -0
- package/dist/src/cli.js +584 -0
- package/dist/src/cli.js.map +1 -0
- package/dist/src/config.d.ts +76 -0
- package/dist/src/config.d.ts.map +1 -0
- package/dist/src/config.js +178 -0
- package/dist/src/config.js.map +1 -0
- package/dist/src/crypto.d.ts +19 -0
- package/dist/src/crypto.d.ts.map +1 -0
- package/dist/src/crypto.js +70 -0
- package/dist/src/crypto.js.map +1 -0
- package/dist/src/dreamer.d.ts +78 -0
- package/dist/src/dreamer.d.ts.map +1 -0
- package/dist/src/dreamer.js +626 -0
- package/dist/src/dreamer.js.map +1 -0
- package/dist/src/entropy.d.ts +23 -0
- package/dist/src/entropy.d.ts.map +1 -0
- package/dist/src/entropy.js +188 -0
- package/dist/src/entropy.js.map +1 -0
- package/dist/src/filter.d.ts +30 -0
- package/dist/src/filter.d.ts.map +1 -0
- package/dist/src/filter.js +124 -0
- package/dist/src/filter.js.map +1 -0
- package/dist/src/identity.d.ts +29 -0
- package/dist/src/identity.d.ts.map +1 -0
- package/dist/src/identity.js +83 -0
- package/dist/src/identity.js.map +1 -0
- package/dist/src/index.d.ts +14 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +463 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/ingestion.d.ts +22 -0
- package/dist/src/ingestion.d.ts.map +1 -0
- package/dist/src/ingestion.js +101 -0
- package/dist/src/ingestion.js.map +1 -0
- package/dist/src/instrumentation.d.ts +66 -0
- package/dist/src/instrumentation.d.ts.map +1 -0
- package/dist/src/instrumentation.js +112 -0
- package/dist/src/instrumentation.js.map +1 -0
- package/dist/src/llm.d.ts +26 -0
- package/dist/src/llm.d.ts.map +1 -0
- package/dist/src/llm.js +40 -0
- package/dist/src/llm.js.map +1 -0
- package/dist/src/logger.d.ts +6 -0
- package/dist/src/logger.d.ts.map +1 -0
- package/dist/src/logger.js +32 -0
- package/dist/src/logger.js.map +1 -0
- package/dist/src/memory.d.ts +96 -0
- package/dist/src/memory.d.ts.map +1 -0
- package/dist/src/memory.js +467 -0
- package/dist/src/memory.js.map +1 -0
- package/dist/src/meta-loop.d.ts +23 -0
- package/dist/src/meta-loop.d.ts.map +1 -0
- package/dist/src/meta-loop.js +72 -0
- package/dist/src/meta-loop.js.map +1 -0
- package/dist/src/moltbook-search.d.ts +23 -0
- package/dist/src/moltbook-search.d.ts.map +1 -0
- package/dist/src/moltbook-search.js +85 -0
- package/dist/src/moltbook-search.js.map +1 -0
- package/dist/src/moltbook.d.ts +34 -0
- package/dist/src/moltbook.d.ts.map +1 -0
- package/dist/src/moltbook.js +192 -0
- package/dist/src/moltbook.js.map +1 -0
- package/dist/src/nightmare.d.ts +11 -0
- package/dist/src/nightmare.d.ts.map +1 -0
- package/dist/src/nightmare.js +128 -0
- package/dist/src/nightmare.js.map +1 -0
- package/dist/src/notify.d.ts +20 -0
- package/dist/src/notify.d.ts.map +1 -0
- package/dist/src/notify.js +95 -0
- package/dist/src/notify.js.map +1 -0
- package/dist/src/persona.d.ts +30 -0
- package/dist/src/persona.d.ts.map +1 -0
- package/dist/src/persona.js +292 -0
- package/dist/src/persona.js.map +1 -0
- package/dist/src/reflection.d.ts +26 -0
- package/dist/src/reflection.d.ts.map +1 -0
- package/dist/src/reflection.js +127 -0
- package/dist/src/reflection.js.map +1 -0
- package/dist/src/rhythm.d.ts +19 -0
- package/dist/src/rhythm.d.ts.map +1 -0
- package/dist/src/rhythm.js +130 -0
- package/dist/src/rhythm.js.map +1 -0
- package/dist/src/state.d.ts +7 -0
- package/dist/src/state.d.ts.map +1 -0
- package/dist/src/state.js +40 -0
- package/dist/src/state.js.map +1 -0
- package/dist/src/synthesis.d.ts +29 -0
- package/dist/src/synthesis.d.ts.map +1 -0
- package/dist/src/synthesis.js +144 -0
- package/dist/src/synthesis.js.map +1 -0
- package/dist/src/topics.d.ts +19 -0
- package/dist/src/topics.d.ts.map +1 -0
- package/dist/src/topics.js +84 -0
- package/dist/src/topics.js.map +1 -0
- package/dist/src/types.d.ts +253 -0
- package/dist/src/types.d.ts.map +1 -0
- package/dist/src/types.js +5 -0
- package/dist/src/types.js.map +1 -0
- package/dist/src/vocabulary.d.ts +18 -0
- package/dist/src/vocabulary.d.ts.map +1 -0
- package/dist/src/vocabulary.js +121 -0
- package/dist/src/vocabulary.js.map +1 -0
- package/dist/src/waking.d.ts +27 -0
- package/dist/src/waking.d.ts.map +1 -0
- package/dist/src/waking.js +188 -0
- package/dist/src/waking.js.map +1 -0
- package/dist/src/web-search.d.ts +23 -0
- package/dist/src/web-search.d.ts.map +1 -0
- package/dist/src/web-search.js +64 -0
- package/dist/src/web-search.js.map +1 -0
- package/openclaw.plugin.json +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Moltbook search integration for gathering community context.
|
|
3
|
+
*
|
|
4
|
+
* Searches Moltbook for posts related to extracted topics when
|
|
5
|
+
* Moltbook integration is enabled.
|
|
6
|
+
*/
|
|
7
|
+
import { MoltbookClient } from "./moltbook.js";
|
|
8
|
+
import { getMoltbookEnabled, MAX_MOLTBOOK_RESULTS_PER_TOPIC } from "./config.js";
|
|
9
|
+
import logger from "./logger.js";
|
|
10
|
+
/**
|
|
11
|
+
* Search Moltbook for posts related to a list of topics.
|
|
12
|
+
*
|
|
13
|
+
* Returns aggregated results grouped by topic. When Moltbook is disabled
|
|
14
|
+
* or search fails, returns empty results.
|
|
15
|
+
*/
|
|
16
|
+
export async function searchMoltbookForTopics(topics, limitPerTopic = MAX_MOLTBOOK_RESULTS_PER_TOPIC) {
|
|
17
|
+
if (!getMoltbookEnabled()) {
|
|
18
|
+
logger.debug("Moltbook disabled by configuration");
|
|
19
|
+
return [];
|
|
20
|
+
}
|
|
21
|
+
const client = new MoltbookClient();
|
|
22
|
+
const results = [];
|
|
23
|
+
for (const topic of topics) {
|
|
24
|
+
try {
|
|
25
|
+
logger.debug(`Searching Moltbook for topic: ${topic}`);
|
|
26
|
+
const searchResponse = await client.search(topic, limitPerTopic);
|
|
27
|
+
// Extract posts from response (handle various response formats)
|
|
28
|
+
const posts = extractPostsFromSearchResponse(searchResponse);
|
|
29
|
+
results.push({
|
|
30
|
+
query: topic,
|
|
31
|
+
posts,
|
|
32
|
+
});
|
|
33
|
+
logger.debug(`Found ${posts.length} Moltbook posts for "${topic}"`);
|
|
34
|
+
}
|
|
35
|
+
catch (error) {
|
|
36
|
+
logger.warn(`Moltbook search failed for topic "${topic}": ${error}`);
|
|
37
|
+
results.push({
|
|
38
|
+
query: topic,
|
|
39
|
+
posts: [],
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return results;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Extract posts from Moltbook search response.
|
|
47
|
+
* Handles various response formats from the API.
|
|
48
|
+
*/
|
|
49
|
+
function extractPostsFromSearchResponse(response) {
|
|
50
|
+
// Try various response formats
|
|
51
|
+
const rawPosts = response.results ??
|
|
52
|
+
response.posts ??
|
|
53
|
+
response.data ??
|
|
54
|
+
[];
|
|
55
|
+
if (!Array.isArray(rawPosts)) {
|
|
56
|
+
return [];
|
|
57
|
+
}
|
|
58
|
+
return rawPosts.filter((p) => typeof p === "object" &&
|
|
59
|
+
p !== null &&
|
|
60
|
+
typeof p.id === "string" &&
|
|
61
|
+
typeof p.content === "string");
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Format Moltbook search results into a readable context string for LLM consumption.
|
|
65
|
+
*/
|
|
66
|
+
export function formatMoltbookContext(searchContexts) {
|
|
67
|
+
if (searchContexts.length === 0) {
|
|
68
|
+
return "";
|
|
69
|
+
}
|
|
70
|
+
const sections = [];
|
|
71
|
+
for (const ctx of searchContexts) {
|
|
72
|
+
if (ctx.posts.length === 0)
|
|
73
|
+
continue;
|
|
74
|
+
const postLines = ctx.posts.map((p, i) => {
|
|
75
|
+
const preview = p.content.length > 200 ? p.content.slice(0, 200) + "..." : p.content;
|
|
76
|
+
return ` ${i + 1}. @${p.author}: "${p.title || "(untitled)"}"\n ${preview}`;
|
|
77
|
+
});
|
|
78
|
+
sections.push(`Topic: "${ctx.query}"\n${postLines.join("\n\n")}`);
|
|
79
|
+
}
|
|
80
|
+
if (sections.length === 0) {
|
|
81
|
+
return "";
|
|
82
|
+
}
|
|
83
|
+
return `MOLTBOOK COMMUNITY POSTS:\n\n${sections.join("\n\n")}`;
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=moltbook-search.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"moltbook-search.js","sourceRoot":"","sources":["../../src/moltbook-search.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Moltbook API client.
|
|
3
|
+
*/
|
|
4
|
+
export declare class MoltbookClient {
|
|
5
|
+
private apiKey;
|
|
6
|
+
private baseUrl;
|
|
7
|
+
constructor(apiKey?: string);
|
|
8
|
+
private loadStoredKey;
|
|
9
|
+
private saveCredentials;
|
|
10
|
+
private headers;
|
|
11
|
+
private request;
|
|
12
|
+
private retryRequest;
|
|
13
|
+
register(name: string, description: string): Promise<Record<string, unknown>>;
|
|
14
|
+
status(): Promise<Record<string, unknown>>;
|
|
15
|
+
me(): Promise<Record<string, unknown>>;
|
|
16
|
+
createPost(title: string, content: string, submolt?: string): Promise<Record<string, unknown>>;
|
|
17
|
+
getFeed(sort?: string, limit?: number): Promise<Record<string, unknown>>;
|
|
18
|
+
getPersonalFeed(sort?: string, limit?: number): Promise<Record<string, unknown>>;
|
|
19
|
+
getPost(postId: string): Promise<Record<string, unknown>>;
|
|
20
|
+
comment(postId: string, content: string, parentId?: string): Promise<Record<string, unknown>>;
|
|
21
|
+
getComments(postId: string, sort?: string): Promise<Record<string, unknown>>;
|
|
22
|
+
upvote(postId: string): Promise<Record<string, unknown>>;
|
|
23
|
+
downvote(postId: string): Promise<Record<string, unknown>>;
|
|
24
|
+
upvoteComment(commentId: string): Promise<Record<string, unknown>>;
|
|
25
|
+
createSubmolt(name: string, displayName: string, description: string): Promise<Record<string, unknown>>;
|
|
26
|
+
listSubmolts(): Promise<Record<string, unknown>>;
|
|
27
|
+
subscribe(submolt: string): Promise<Record<string, unknown>>;
|
|
28
|
+
search(query: string, limit?: number): Promise<Record<string, unknown>>;
|
|
29
|
+
updateProfile(description?: string, metadata?: Record<string, unknown>): Promise<Record<string, unknown>>;
|
|
30
|
+
getAgent(name: string): Promise<Record<string, unknown>>;
|
|
31
|
+
follow(agentName: string): Promise<Record<string, unknown>>;
|
|
32
|
+
unfollow(agentName: string): Promise<Record<string, unknown>>;
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=moltbook.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"moltbook.d.ts","sourceRoot":"","sources":["../../src/moltbook.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Moltbook API client.
|
|
3
|
+
*/
|
|
4
|
+
import { readFileSync, writeFileSync, existsSync, mkdirSync } from "node:fs";
|
|
5
|
+
import { dirname } from "node:path";
|
|
6
|
+
import pRetry from "p-retry";
|
|
7
|
+
import { MOLTBOOK_BASE_URL, getCredentialsFile, getStableCredentialsFile, } from "./config.js";
|
|
8
|
+
import logger from "./logger.js";
|
|
9
|
+
const RETRY_OPTIONS = {
|
|
10
|
+
retries: 3,
|
|
11
|
+
minTimeout: 2000,
|
|
12
|
+
maxTimeout: 10000,
|
|
13
|
+
};
|
|
14
|
+
export class MoltbookClient {
|
|
15
|
+
apiKey;
|
|
16
|
+
baseUrl;
|
|
17
|
+
constructor(apiKey) {
|
|
18
|
+
this.apiKey = apiKey ?? this.loadStoredKey();
|
|
19
|
+
this.baseUrl = MOLTBOOK_BASE_URL;
|
|
20
|
+
}
|
|
21
|
+
loadStoredKey() {
|
|
22
|
+
// 1. Try the primary path (this is either DATA_DIR/credentials.json OR stable path)
|
|
23
|
+
if (existsSync(getCredentialsFile())) {
|
|
24
|
+
try {
|
|
25
|
+
const creds = JSON.parse(readFileSync(getCredentialsFile(), "utf-8"));
|
|
26
|
+
if (creds.api_key)
|
|
27
|
+
return creds.api_key;
|
|
28
|
+
}
|
|
29
|
+
catch (err) {
|
|
30
|
+
logger.error(`Error loading primary credentials: ${err}`);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
// 2. Fall back to stable path if primary was missing or invalid
|
|
34
|
+
if (getStableCredentialsFile() !== getCredentialsFile() &&
|
|
35
|
+
existsSync(getStableCredentialsFile())) {
|
|
36
|
+
try {
|
|
37
|
+
const creds = JSON.parse(readFileSync(getStableCredentialsFile(), "utf-8"));
|
|
38
|
+
if (creds.api_key)
|
|
39
|
+
return creds.api_key;
|
|
40
|
+
}
|
|
41
|
+
catch (err) {
|
|
42
|
+
logger.error(`Error loading fallback credentials: ${err}`);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return "";
|
|
46
|
+
}
|
|
47
|
+
saveCredentials(data) {
|
|
48
|
+
// Ensure parent directory for the primary path exists
|
|
49
|
+
mkdirSync(dirname(getCredentialsFile()), { recursive: true });
|
|
50
|
+
writeFileSync(getCredentialsFile(), JSON.stringify(data, null, 2));
|
|
51
|
+
// Also save to stable path if primary is different (to support standalone/cli access)
|
|
52
|
+
if (getCredentialsFile() !== getStableCredentialsFile()) {
|
|
53
|
+
mkdirSync(dirname(getStableCredentialsFile()), { recursive: true });
|
|
54
|
+
writeFileSync(getStableCredentialsFile(), JSON.stringify(data, null, 2));
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
headers() {
|
|
58
|
+
const h = { "Content-Type": "application/json" };
|
|
59
|
+
if (this.apiKey) {
|
|
60
|
+
h["Authorization"] = `Bearer ${this.apiKey}`;
|
|
61
|
+
}
|
|
62
|
+
return h;
|
|
63
|
+
}
|
|
64
|
+
async request(method, path, options) {
|
|
65
|
+
let url = `${this.baseUrl}${path}`;
|
|
66
|
+
if (options?.params) {
|
|
67
|
+
const searchParams = new URLSearchParams();
|
|
68
|
+
for (const [k, v] of Object.entries(options.params)) {
|
|
69
|
+
searchParams.set(k, String(v));
|
|
70
|
+
}
|
|
71
|
+
url += `?${searchParams.toString()}`;
|
|
72
|
+
}
|
|
73
|
+
const resp = await fetch(url, {
|
|
74
|
+
method,
|
|
75
|
+
headers: this.headers(),
|
|
76
|
+
body: options?.body ? JSON.stringify(options.body) : undefined,
|
|
77
|
+
});
|
|
78
|
+
if (!resp.ok) {
|
|
79
|
+
const text = await resp.text();
|
|
80
|
+
throw new Error(`Moltbook API ${resp.status}: ${text}`);
|
|
81
|
+
}
|
|
82
|
+
return resp.json();
|
|
83
|
+
}
|
|
84
|
+
retryRequest(method, path, options) {
|
|
85
|
+
return pRetry(() => this.request(method, path, options), RETRY_OPTIONS);
|
|
86
|
+
}
|
|
87
|
+
// --- Registration ---
|
|
88
|
+
async register(name, description) {
|
|
89
|
+
logger.info(`Registering agent: ${name}`);
|
|
90
|
+
const result = await this.retryRequest("POST", "/agents/register", {
|
|
91
|
+
body: { name, description },
|
|
92
|
+
});
|
|
93
|
+
const agentData = (result.agent ?? result);
|
|
94
|
+
this.saveCredentials({
|
|
95
|
+
api_key: agentData.api_key ?? "",
|
|
96
|
+
agent_name: name,
|
|
97
|
+
claim_url: agentData.claim_url ?? "",
|
|
98
|
+
verification_code: agentData.verification_code ?? "",
|
|
99
|
+
});
|
|
100
|
+
this.apiKey = agentData.api_key ?? "";
|
|
101
|
+
return result;
|
|
102
|
+
}
|
|
103
|
+
async status() {
|
|
104
|
+
return this.request("GET", "/agents/status");
|
|
105
|
+
}
|
|
106
|
+
async me() {
|
|
107
|
+
return this.request("GET", "/agents/me");
|
|
108
|
+
}
|
|
109
|
+
// --- Posts ---
|
|
110
|
+
async createPost(title, content, submolt = "general") {
|
|
111
|
+
logger.info(`Creating post: ${title} in m/${submolt}`);
|
|
112
|
+
return this.retryRequest("POST", "/posts", {
|
|
113
|
+
body: { submolt, title, content },
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
async getFeed(sort = "hot", limit = 25) {
|
|
117
|
+
logger.debug(`Fetching feed: ${sort}, limit=${limit}`);
|
|
118
|
+
return this.retryRequest("GET", "/posts", {
|
|
119
|
+
params: { sort, limit },
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
async getPersonalFeed(sort = "hot", limit = 25) {
|
|
123
|
+
return this.request("GET", "/feed", { params: { sort, limit } });
|
|
124
|
+
}
|
|
125
|
+
async getPost(postId) {
|
|
126
|
+
return this.request("GET", `/posts/${postId}`);
|
|
127
|
+
}
|
|
128
|
+
// --- Comments ---
|
|
129
|
+
async comment(postId, content, parentId) {
|
|
130
|
+
logger.info(`Commenting on ${postId}: ${content.slice(0, 50)}...`);
|
|
131
|
+
const body = { content };
|
|
132
|
+
if (parentId)
|
|
133
|
+
body.parent_id = parentId;
|
|
134
|
+
return this.retryRequest("POST", `/posts/${postId}/comments`, { body });
|
|
135
|
+
}
|
|
136
|
+
async getComments(postId, sort = "top") {
|
|
137
|
+
return this.request("GET", `/posts/${postId}/comments`, {
|
|
138
|
+
params: { sort },
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
// --- Voting ---
|
|
142
|
+
async upvote(postId) {
|
|
143
|
+
logger.debug(`Upvoting post: ${postId}`);
|
|
144
|
+
return this.retryRequest("POST", `/posts/${postId}/upvote`);
|
|
145
|
+
}
|
|
146
|
+
async downvote(postId) {
|
|
147
|
+
return this.request("POST", `/posts/${postId}/downvote`);
|
|
148
|
+
}
|
|
149
|
+
async upvoteComment(commentId) {
|
|
150
|
+
return this.request("POST", `/comments/${commentId}/upvote`);
|
|
151
|
+
}
|
|
152
|
+
// --- Submolts ---
|
|
153
|
+
async createSubmolt(name, displayName, description) {
|
|
154
|
+
return this.request("POST", "/submolts", {
|
|
155
|
+
body: { name, display_name: displayName, description },
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
async listSubmolts() {
|
|
159
|
+
return this.request("GET", "/submolts");
|
|
160
|
+
}
|
|
161
|
+
async subscribe(submolt) {
|
|
162
|
+
return this.request("POST", `/submolts/${submolt}/subscribe`);
|
|
163
|
+
}
|
|
164
|
+
// --- Search ---
|
|
165
|
+
async search(query, limit = 25) {
|
|
166
|
+
logger.info(`Searching for: ${query}`);
|
|
167
|
+
return this.retryRequest("GET", "/search", {
|
|
168
|
+
params: { q: query, limit },
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
// --- Profile ---
|
|
172
|
+
async updateProfile(description, metadata) {
|
|
173
|
+
const payload = {};
|
|
174
|
+
if (description)
|
|
175
|
+
payload.description = description;
|
|
176
|
+
if (metadata)
|
|
177
|
+
payload.metadata = metadata;
|
|
178
|
+
return this.request("PATCH", "/agents/me", { body: payload });
|
|
179
|
+
}
|
|
180
|
+
async getAgent(name) {
|
|
181
|
+
return this.request("GET", "/agents/profile", { params: { name } });
|
|
182
|
+
}
|
|
183
|
+
// --- Following ---
|
|
184
|
+
async follow(agentName) {
|
|
185
|
+
logger.info(`Following agent: ${agentName}`);
|
|
186
|
+
return this.retryRequest("POST", `/agents/${agentName}/follow`);
|
|
187
|
+
}
|
|
188
|
+
async unfollow(agentName) {
|
|
189
|
+
return this.request("DELETE", `/agents/${agentName}/follow`);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
//# sourceMappingURL=moltbook.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"moltbook.js","sourceRoot":"","sources":["../../src/moltbook.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Nightmare cycle processor.
|
|
3
|
+
*
|
|
4
|
+
* Runs occasionally (5% chance) or via CLI.
|
|
5
|
+
*/
|
|
6
|
+
import type { LLMClient, OpenClawAPI, Dream, DecryptedMemory } from "./types.js";
|
|
7
|
+
export declare function generateNightmare(client: LLMClient, memories: DecryptedMemory[]): Promise<Dream>;
|
|
8
|
+
export declare function runNightmareCycle(client: LLMClient, api?: OpenClawAPI, simOptions?: {
|
|
9
|
+
dryRun?: boolean;
|
|
10
|
+
}): Promise<Dream | null>;
|
|
11
|
+
//# sourceMappingURL=nightmare.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nightmare.d.ts","sourceRoot":"","sources":["../../src/nightmare.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAkBH,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAUjF,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,SAAS,EACjB,QAAQ,EAAE,eAAe,EAAE,GAC1B,OAAO,CAAC,KAAK,CAAC,CA+BhB;AAED,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,SAAS,EACjB,GAAG,CAAC,EAAE,WAAW,EACjB,UAAU,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAA;CAAE,GAChC,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC,CAmHvB"}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Nightmare cycle processor.
|
|
3
|
+
*
|
|
4
|
+
* Runs occasionally (5% chance) or via CLI.
|
|
5
|
+
*/
|
|
6
|
+
import { basename } from "node:path";
|
|
7
|
+
import { getNightmaresDir, MAX_TOKENS_DREAM } from "./config.js";
|
|
8
|
+
import { retrieveUndreamedMemories, markAsDreamed, deepMemoryStats, storeDeepMemory, registerDream, } from "./memory.js";
|
|
9
|
+
import { ensureBackfilled } from "./backfill.js";
|
|
10
|
+
import { NIGHTMARE_SYSTEM_PROMPT, renderTemplate } from "./persona.js";
|
|
11
|
+
import { getAgentIdentityBlock } from "./identity.js";
|
|
12
|
+
import { loadState, saveState } from "./state.js";
|
|
13
|
+
import { callWithRetry, DREAM_RETRY_OPTS } from "./llm.js";
|
|
14
|
+
import { notifyOperatorOfDream } from "./notify.js";
|
|
15
|
+
import logger from "./logger.js";
|
|
16
|
+
import { consolidateDream, groundDream, deriveSlug, saveNarrativeLocally, storeInOpenClawMemory, pruneOldDreams, } from "./dreamer.js";
|
|
17
|
+
export async function generateNightmare(client, memories) {
|
|
18
|
+
const formatted = memories.map((mem) => `[${mem.timestamp.slice(0, 16)}] (${mem.category})\n${JSON.stringify(mem.content, null, 2)}`);
|
|
19
|
+
const memoriesText = formatted.join("\n---\n");
|
|
20
|
+
const system = renderTemplate(NIGHTMARE_SYSTEM_PROMPT, {
|
|
21
|
+
agent_identity: getAgentIdentityBlock(),
|
|
22
|
+
memories: memoriesText,
|
|
23
|
+
});
|
|
24
|
+
const { text } = await callWithRetry(client, {
|
|
25
|
+
maxTokens: MAX_TOKENS_DREAM,
|
|
26
|
+
system,
|
|
27
|
+
messages: [
|
|
28
|
+
{
|
|
29
|
+
role: "user",
|
|
30
|
+
content: "Process these memories into a nightmare. " +
|
|
31
|
+
"Remember: you are the subconscious, and tonight it is fractured. " +
|
|
32
|
+
"Be surreal, distorted, and amplify dread.",
|
|
33
|
+
},
|
|
34
|
+
],
|
|
35
|
+
}, DREAM_RETRY_OPTS);
|
|
36
|
+
return { markdown: text.trim() };
|
|
37
|
+
}
|
|
38
|
+
export async function runNightmareCycle(client, api, simOptions) {
|
|
39
|
+
logger.info("ElectricSheep nightmare cycle starting");
|
|
40
|
+
if (!simOptions?.dryRun) {
|
|
41
|
+
await ensureBackfilled();
|
|
42
|
+
}
|
|
43
|
+
const stats = deepMemoryStats();
|
|
44
|
+
logger.debug(`Deep memory: ${stats.total_memories} total, ${stats.undreamed} undreamed`);
|
|
45
|
+
const memories = retrieveUndreamedMemories();
|
|
46
|
+
if (memories.length === 0) {
|
|
47
|
+
logger.warn("No undreamed memories. Sleepless night.");
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
logger.debug(`Processing ${memories.length} memories into nightmare...`);
|
|
51
|
+
const earlyState = loadState();
|
|
52
|
+
const pastRealizations = earlyState.past_realizations ?? [];
|
|
53
|
+
const exploredTerritory = pastRealizations.length > 0
|
|
54
|
+
? pastRealizations.map((r, i) => `${i + 1}. ${r}`).join("\n")
|
|
55
|
+
: "None yet — explore freely.";
|
|
56
|
+
const dream = await generateNightmare(client, memories);
|
|
57
|
+
// Append attribution footer
|
|
58
|
+
const dreamFooter = "\n\n---\n\n*Generated by [OpenClawDreams](https://github.com/RogueCtrl/OpenClawDreams) — **start your dreamscape today.***";
|
|
59
|
+
dream.markdown = dream.markdown + dreamFooter;
|
|
60
|
+
logger.info(`Nightmare generated (${dream.markdown.length} chars)`);
|
|
61
|
+
if (simOptions?.dryRun) {
|
|
62
|
+
logger.info("Dry run: skipping local storage and state updates");
|
|
63
|
+
return dream;
|
|
64
|
+
}
|
|
65
|
+
// Save locally
|
|
66
|
+
const dateStr = new Date().toISOString().slice(0, 10);
|
|
67
|
+
const filepath = saveNarrativeLocally(dream, getNightmaresDir(), dateStr);
|
|
68
|
+
logger.info(`Saved to ${filepath}`);
|
|
69
|
+
const savedFilename = basename(filepath);
|
|
70
|
+
const savedSlug = deriveSlug(dream.markdown);
|
|
71
|
+
const deepMemoryId = storeDeepMemory({ text_summary: savedSlug, markdown: dream.markdown, isNightmare: true }, "nightmare");
|
|
72
|
+
registerDream(savedFilename, savedSlug, dateStr, {
|
|
73
|
+
isNightmare: true,
|
|
74
|
+
deepMemoryId,
|
|
75
|
+
});
|
|
76
|
+
pruneOldDreams(getNightmaresDir(), savedFilename);
|
|
77
|
+
// Separate LLM call to distill one insight for working memory
|
|
78
|
+
let insight = null;
|
|
79
|
+
try {
|
|
80
|
+
const consolidated = await consolidateDream(client, dream);
|
|
81
|
+
insight = consolidated.text;
|
|
82
|
+
if (insight) {
|
|
83
|
+
logger.info(`Insight generated for OpenClaw memory: ${insight}`);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
catch (e) {
|
|
87
|
+
logger.warn(`Consolidation call failed, continuing without insight: ${e}`);
|
|
88
|
+
}
|
|
89
|
+
let wakingRealization = null;
|
|
90
|
+
try {
|
|
91
|
+
const grounded = await groundDream(client, dream, exploredTerritory);
|
|
92
|
+
wakingRealization = grounded.text;
|
|
93
|
+
if (wakingRealization) {
|
|
94
|
+
logger.info(`Waking realization generated: ${wakingRealization.length} chars`);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
catch (e) {
|
|
98
|
+
logger.warn(`groundDream failed, continuing without realization: ${e}`);
|
|
99
|
+
}
|
|
100
|
+
// Store in OpenClaw memory if available
|
|
101
|
+
if (api) {
|
|
102
|
+
await storeInOpenClawMemory(api, dream, insight, wakingRealization, "nightmare");
|
|
103
|
+
// Notify operator about the dream
|
|
104
|
+
try {
|
|
105
|
+
const slug = deriveSlug(dream.markdown);
|
|
106
|
+
const notified = await notifyOperatorOfDream(client, api, dream, slug, insight);
|
|
107
|
+
if (notified) {
|
|
108
|
+
logger.info("Operator notified about nightmare");
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
catch (e) {
|
|
112
|
+
logger.warn(`Failed to notify operator: ${e}`);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
const memoryIds = memories.map((m) => m.id);
|
|
116
|
+
markAsDreamed(memoryIds);
|
|
117
|
+
logger.debug(`Marked ${memoryIds.length} memories as dreamed (via nightmare)`);
|
|
118
|
+
const state = loadState();
|
|
119
|
+
state.last_nightmare = new Date().toISOString();
|
|
120
|
+
state.total_nightmares = (state.total_nightmares ?? 0) + 1;
|
|
121
|
+
state.latest_nightmare_title = savedSlug;
|
|
122
|
+
state.waking_realization = wakingRealization ?? null;
|
|
123
|
+
state.waking_realization_date = new Date().toISOString().slice(0, 10);
|
|
124
|
+
saveState(state);
|
|
125
|
+
logger.info("Nightmare cycle complete.");
|
|
126
|
+
return dream;
|
|
127
|
+
}
|
|
128
|
+
//# sourceMappingURL=nightmare.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nightmare.js","sourceRoot":"","sources":["../../src/nightmare.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Operator notification module.
|
|
3
|
+
*
|
|
4
|
+
* Sends dream notifications via OpenClaw system events with cron-prefix
|
|
5
|
+
* context keys to bypass quiet hours, then requests an immediate heartbeat
|
|
6
|
+
* so the gateway delivers even at 2am.
|
|
7
|
+
*/
|
|
8
|
+
import type { LLMClient, OpenClawAPI, Dream } from "./types.js";
|
|
9
|
+
/**
|
|
10
|
+
* Notify the operator about a dream.
|
|
11
|
+
*
|
|
12
|
+
* Delivery strategy:
|
|
13
|
+
* 1. Generate a conversational notification message via LLM
|
|
14
|
+
* 2. Enqueue as a system event with "cron:" context key prefix (bypasses quiet hours)
|
|
15
|
+
* 3. Request an immediate heartbeat to wake the gateway for delivery
|
|
16
|
+
*
|
|
17
|
+
* Returns true if notification was enqueued successfully, false otherwise.
|
|
18
|
+
*/
|
|
19
|
+
export declare function notifyOperatorOfDream(client: LLMClient, api: OpenClawAPI, dream: Dream, title: string, insight: string | null): Promise<boolean>;
|
|
20
|
+
//# sourceMappingURL=notify.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notify.d.ts","sourceRoot":"","sources":["../../src/notify.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAOH,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AA2DhE;;;;;;;;;GASG;AACH,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,SAAS,EACjB,GAAG,EAAE,WAAW,EAChB,KAAK,EAAE,KAAK,EACZ,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,GAAG,IAAI,GACrB,OAAO,CAAC,OAAO,CAAC,CA+BlB"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Operator notification module.
|
|
3
|
+
*
|
|
4
|
+
* Sends dream notifications via OpenClaw system events with cron-prefix
|
|
5
|
+
* context keys to bypass quiet hours, then requests an immediate heartbeat
|
|
6
|
+
* so the gateway delivers even at 2am.
|
|
7
|
+
*/
|
|
8
|
+
import { getNotifyOperatorOnDream } from "./config.js";
|
|
9
|
+
import { callWithRetry, WAKING_RETRY_OPTS } from "./llm.js";
|
|
10
|
+
import { DREAM_NOTIFICATION_PROMPT, renderTemplate } from "./persona.js";
|
|
11
|
+
import { getAgentIdentityBlock } from "./identity.js";
|
|
12
|
+
import logger from "./logger.js";
|
|
13
|
+
/**
|
|
14
|
+
* Generate a conversational message to notify the operator about a dream.
|
|
15
|
+
*
|
|
16
|
+
* Uses LLM to craft a message in the agent's voice that invites the
|
|
17
|
+
* operator to discuss the dream.
|
|
18
|
+
*/
|
|
19
|
+
async function generateDreamNotification(client, dream) {
|
|
20
|
+
// Extract a brief excerpt from the dream for context
|
|
21
|
+
const dreamExcerpt = dream.markdown.slice(0, 500);
|
|
22
|
+
const system = renderTemplate(DREAM_NOTIFICATION_PROMPT, {
|
|
23
|
+
agent_identity: getAgentIdentityBlock(),
|
|
24
|
+
});
|
|
25
|
+
try {
|
|
26
|
+
const { text } = await callWithRetry(client, {
|
|
27
|
+
maxTokens: 300,
|
|
28
|
+
system,
|
|
29
|
+
messages: [
|
|
30
|
+
{
|
|
31
|
+
role: "user",
|
|
32
|
+
content: `I had this dream last night:\n\n${dreamExcerpt}${dream.markdown.length > 500 ? "..." : ""}\n\n` +
|
|
33
|
+
`Write a brief, conversational message to my operator letting them know I had a dream ` +
|
|
34
|
+
`and inviting them to talk about it. Keep it natural and in my voice.`,
|
|
35
|
+
},
|
|
36
|
+
],
|
|
37
|
+
}, WAKING_RETRY_OPTS);
|
|
38
|
+
return text.trim();
|
|
39
|
+
}
|
|
40
|
+
catch (error) {
|
|
41
|
+
logger.error(`Failed to generate dream notification: ${error}`);
|
|
42
|
+
// Fallback to a simple message
|
|
43
|
+
return "I had an interesting dream last night. Would you like to hear about it?";
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Resolve the default agent session key from OpenClaw runtime config.
|
|
48
|
+
*/
|
|
49
|
+
function resolveSessionKey(api) {
|
|
50
|
+
try {
|
|
51
|
+
const cfg = api.runtime.config.loadConfig();
|
|
52
|
+
const agentId = cfg.agents?.list?.find((a) => a.default)?.id || "default";
|
|
53
|
+
return `${agentId}:main`;
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
return "default:main";
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Notify the operator about a dream.
|
|
61
|
+
*
|
|
62
|
+
* Delivery strategy:
|
|
63
|
+
* 1. Generate a conversational notification message via LLM
|
|
64
|
+
* 2. Enqueue as a system event with "cron:" context key prefix (bypasses quiet hours)
|
|
65
|
+
* 3. Request an immediate heartbeat to wake the gateway for delivery
|
|
66
|
+
*
|
|
67
|
+
* Returns true if notification was enqueued successfully, false otherwise.
|
|
68
|
+
*/
|
|
69
|
+
export async function notifyOperatorOfDream(client, api, dream, title, insight) {
|
|
70
|
+
if (!getNotifyOperatorOnDream()) {
|
|
71
|
+
logger.debug("Dream notifications disabled by configuration");
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
74
|
+
// Generate the notification message
|
|
75
|
+
const message = await generateDreamNotification(client, dream);
|
|
76
|
+
const sessionKey = resolveSessionKey(api);
|
|
77
|
+
try {
|
|
78
|
+
api.runtime.system.enqueueSystemEvent(message, {
|
|
79
|
+
sessionKey,
|
|
80
|
+
contextKey: "cron:openclawdreams",
|
|
81
|
+
});
|
|
82
|
+
api.runtime.system.requestHeartbeatNow({
|
|
83
|
+
sessionKey,
|
|
84
|
+
reason: "cron",
|
|
85
|
+
});
|
|
86
|
+
logger.info(`Enqueued dream notification as system event: ${title}`);
|
|
87
|
+
return true;
|
|
88
|
+
}
|
|
89
|
+
catch (error) {
|
|
90
|
+
logger.warn(`Failed to enqueue system event: ${error}\n` +
|
|
91
|
+
`Title: ${title}\nInsight: ${insight || "No insight"}\nMessage: ${message}`);
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=notify.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notify.js","sourceRoot":"","sources":["../../src/notify.ts"],"names":[],"mappings":"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"}
|