openclawdreams 1.5.0 → 1.5.1
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 +25 -0
- package/dist/src/config.d.ts +4 -0
- package/dist/src/config.js +8 -1
- package/dist/src/moltbook.js +31 -4
- package/dist/test/credentials_fallback.test.d.ts +2 -0
- package/dist/test/credentials_fallback.test.js +65 -0
- package/dist/test/moltbook.test.js +22 -1
- package/openclaw.plugin.json +1 -1
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,31 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
|
4
4
|
|
|
5
|
+
### [1.5.1](https://github.com/RogueCtrl/OpenClawDreams/compare/v1.2.2...v1.5.1) (2026-03-08)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
### Features
|
|
9
|
+
|
|
10
|
+
* dream pipeline v1.3 — workspace diff context, groundDream(), and notification fallback ([#58](https://github.com/RogueCtrl/OpenClawDreams/issues/58)) ([c683fb6](https://github.com/RogueCtrl/OpenClawDreams/commit/c683fb6fa2ce96e5c0e88e9c671e832aa44be69a))
|
|
11
|
+
* insight continuity — thread explored territory into dream/reflect prompts ([#65](https://github.com/RogueCtrl/OpenClawDreams/issues/65)) ([c7bdee1](https://github.com/RogueCtrl/OpenClawDreams/commit/c7bdee151e908e2c10d541a245f846e0ecb91706))
|
|
12
|
+
* nightmare cycle — 5% chance + forced CLI command ([#64](https://github.com/RogueCtrl/OpenClawDreams/issues/64)) ([50c261c](https://github.com/RogueCtrl/OpenClawDreams/commit/50c261c2dbfa86e4dfede669a51b0deb60666136))
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
### Bug Fixes
|
|
16
|
+
|
|
17
|
+
* DST-safe scheduler with catch-up window ([#54](https://github.com/RogueCtrl/OpenClawDreams/issues/54)) ([230a943](https://github.com/RogueCtrl/OpenClawDreams/commit/230a9436eadf4e374595a772d2b2de3ee910b6f6))
|
|
18
|
+
* prettier formatting — cli.ts and index.ts ([#52](https://github.com/RogueCtrl/OpenClawDreams/issues/52)) ([93df3d8](https://github.com/RogueCtrl/OpenClawDreams/commit/93df3d8e44a62ae79135eef765604786815d4f91))
|
|
19
|
+
* resolve MoltbookClient credentials from stable fallback path when DATA_DIR unset (fixes [#70](https://github.com/RogueCtrl/OpenClawDreams/issues/70)) ([48d3019](https://github.com/RogueCtrl/OpenClawDreams/commit/48d30191faa457a5dca9171816844758dfd7844a))
|
|
20
|
+
* run tests sequentially to prevent env var race condition ([#67](https://github.com/RogueCtrl/OpenClawDreams/issues/67)) ([22f0002](https://github.com/RogueCtrl/OpenClawDreams/commit/22f00022b4224422fa7fe0cd1b9c8dde6f8c5b2c))
|
|
21
|
+
* run tests with --test-isolation=process to prevent ESM module cache contamination between test files ([f53a222](https://github.com/RogueCtrl/OpenClawDreams/commit/f53a222a31588d4477bd034cc3764b1011801993))
|
|
22
|
+
* skip workspace diff on iCloud/sensitive paths; add workspaceDiffEnabled config ([dfe6b51](https://github.com/RogueCtrl/OpenClawDreams/commit/dfe6b51ac0ded5ba4ee9609089053cddb774221c))
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
### Documentation
|
|
26
|
+
|
|
27
|
+
* remove roadmap from README and ROADMAP.md (tracked externally) ([9e8620d](https://github.com/RogueCtrl/OpenClawDreams/commit/9e8620dcc2e9bb176cef624a5c7bdfae026d2ced))
|
|
28
|
+
* update AGENTS.md and README for v1.3.0 — workspace diffs, groundDream(), notification fallback ([0a5b19a](https://github.com/RogueCtrl/OpenClawDreams/commit/0a5b19ab4a7a1e84b59ad5e4216be4b335eb767f))
|
|
29
|
+
|
|
5
30
|
## [1.5.0](https://github.com/RogueCtrl/OpenClawDreams/compare/v1.2.2...v1.5.0) (2026-03-08)
|
|
6
31
|
|
|
7
32
|
|
package/dist/src/config.d.ts
CHANGED
|
@@ -6,6 +6,10 @@ export declare const DATA_DIR: string;
|
|
|
6
6
|
export declare const MEMORY_DIR: string;
|
|
7
7
|
export declare const DREAMS_DIR: string;
|
|
8
8
|
export declare const NIGHTMARES_DIR: string;
|
|
9
|
+
/** Stable fallback path for credentials when DATA_DIR is unset/volatile. */
|
|
10
|
+
export declare const STABLE_CONFIG_DIR: string;
|
|
11
|
+
export declare const STABLE_CREDENTIALS_FILE: string;
|
|
12
|
+
/** Primary credentials file path. Resolves to STABLE_CREDENTIALS_FILE if DATA_DIR is default/unset. */
|
|
9
13
|
export declare const CREDENTIALS_FILE: string;
|
|
10
14
|
export declare const AGENT_NAME: string;
|
|
11
15
|
export declare const AGENT_MODEL: string;
|
package/dist/src/config.js
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import { config } from "dotenv";
|
|
5
5
|
import { mkdirSync } from "node:fs";
|
|
6
|
+
import { homedir } from "node:os";
|
|
6
7
|
import { dirname, resolve } from "node:path";
|
|
7
8
|
import { fileURLToPath } from "node:url";
|
|
8
9
|
config({ quiet: true });
|
|
@@ -14,7 +15,13 @@ export const DATA_DIR = resolve(BASE_DIR, "data");
|
|
|
14
15
|
export const MEMORY_DIR = resolve(DATA_DIR, "memory");
|
|
15
16
|
export const DREAMS_DIR = resolve(DATA_DIR, "dreams");
|
|
16
17
|
export const NIGHTMARES_DIR = resolve(DATA_DIR, "nightmares");
|
|
17
|
-
|
|
18
|
+
/** Stable fallback path for credentials when DATA_DIR is unset/volatile. */
|
|
19
|
+
export const STABLE_CONFIG_DIR = resolve(homedir(), ".config", "openclawdreams");
|
|
20
|
+
export const STABLE_CREDENTIALS_FILE = resolve(STABLE_CONFIG_DIR, "credentials.json");
|
|
21
|
+
/** Primary credentials file path. Resolves to STABLE_CREDENTIALS_FILE if DATA_DIR is default/unset. */
|
|
22
|
+
export const CREDENTIALS_FILE = process.env.OPENCLAWDREAMS_DATA_DIR
|
|
23
|
+
? resolve(DATA_DIR, "credentials.json")
|
|
24
|
+
: STABLE_CREDENTIALS_FILE;
|
|
18
25
|
// Ensure directories exist
|
|
19
26
|
for (const dir of [DATA_DIR, MEMORY_DIR, DREAMS_DIR, NIGHTMARES_DIR]) {
|
|
20
27
|
mkdirSync(dir, { recursive: true });
|
package/dist/src/moltbook.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Moltbook API client.
|
|
3
3
|
*/
|
|
4
|
-
import { readFileSync, writeFileSync, existsSync } from "node:fs";
|
|
4
|
+
import { readFileSync, writeFileSync, existsSync, mkdirSync } from "node:fs";
|
|
5
|
+
import { dirname } from "node:path";
|
|
5
6
|
import pRetry from "p-retry";
|
|
6
|
-
import { MOLTBOOK_BASE_URL, CREDENTIALS_FILE } from "./config.js";
|
|
7
|
+
import { MOLTBOOK_BASE_URL, CREDENTIALS_FILE, STABLE_CREDENTIALS_FILE, } from "./config.js";
|
|
7
8
|
import logger from "./logger.js";
|
|
8
9
|
const RETRY_OPTIONS = {
|
|
9
10
|
retries: 3,
|
|
@@ -18,14 +19,40 @@ export class MoltbookClient {
|
|
|
18
19
|
this.baseUrl = MOLTBOOK_BASE_URL;
|
|
19
20
|
}
|
|
20
21
|
loadStoredKey() {
|
|
22
|
+
// 1. Try the primary path (this is either DATA_DIR/credentials.json OR stable path)
|
|
21
23
|
if (existsSync(CREDENTIALS_FILE)) {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
+
try {
|
|
25
|
+
const creds = JSON.parse(readFileSync(CREDENTIALS_FILE, "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 (STABLE_CREDENTIALS_FILE !== CREDENTIALS_FILE &&
|
|
35
|
+
existsSync(STABLE_CREDENTIALS_FILE)) {
|
|
36
|
+
try {
|
|
37
|
+
const creds = JSON.parse(readFileSync(STABLE_CREDENTIALS_FILE, "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
|
+
}
|
|
24
44
|
}
|
|
25
45
|
return "";
|
|
26
46
|
}
|
|
27
47
|
saveCredentials(data) {
|
|
48
|
+
// Ensure parent directory for the primary path exists
|
|
49
|
+
mkdirSync(dirname(CREDENTIALS_FILE), { recursive: true });
|
|
28
50
|
writeFileSync(CREDENTIALS_FILE, JSON.stringify(data, null, 2));
|
|
51
|
+
// Also save to stable path if primary is different (to support standalone/cli access)
|
|
52
|
+
if (CREDENTIALS_FILE !== STABLE_CREDENTIALS_FILE) {
|
|
53
|
+
mkdirSync(dirname(STABLE_CREDENTIALS_FILE), { recursive: true });
|
|
54
|
+
writeFileSync(STABLE_CREDENTIALS_FILE, JSON.stringify(data, null, 2));
|
|
55
|
+
}
|
|
29
56
|
}
|
|
30
57
|
headers() {
|
|
31
58
|
const h = { "Content-Type": "application/json" };
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { describe, it, before, after, mock } from "node:test";
|
|
2
|
+
import assert from "node:assert/strict";
|
|
3
|
+
import { mkdtempSync, rmSync, mkdirSync, writeFileSync, existsSync, readFileSync, } from "node:fs";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import { tmpdir } from "node:os";
|
|
6
|
+
// Fake home dir
|
|
7
|
+
const fakeHome = mkdtempSync(join(tmpdir(), "es-fallback-test-home-"));
|
|
8
|
+
process.env.HOME = fakeHome;
|
|
9
|
+
// Unset DATA_DIR to ensure fallback path is used
|
|
10
|
+
delete process.env.OPENCLAWDREAMS_DATA_DIR;
|
|
11
|
+
// Import after setting HOME
|
|
12
|
+
const { STABLE_CREDENTIALS_FILE, CREDENTIALS_FILE } = await import("../src/config.js");
|
|
13
|
+
const { MoltbookClient } = await import("../src/moltbook.js");
|
|
14
|
+
function mockFetchJson(body, status = 200) {
|
|
15
|
+
return mock.fn(async () => {
|
|
16
|
+
return new Response(JSON.stringify(body), {
|
|
17
|
+
status,
|
|
18
|
+
headers: { "Content-Type": "application/json" },
|
|
19
|
+
});
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
describe("MoltbookClient Credentials Fallback", () => {
|
|
23
|
+
let originalFetch;
|
|
24
|
+
before(() => {
|
|
25
|
+
originalFetch = globalThis.fetch;
|
|
26
|
+
});
|
|
27
|
+
after(() => {
|
|
28
|
+
globalThis.fetch = originalFetch;
|
|
29
|
+
rmSync(fakeHome, { recursive: true, force: true });
|
|
30
|
+
});
|
|
31
|
+
it("resolves CREDENTIALS_FILE to stable fallback when DATA_DIR is unset", () => {
|
|
32
|
+
assert.equal(CREDENTIALS_FILE, STABLE_CREDENTIALS_FILE);
|
|
33
|
+
assert.ok(CREDENTIALS_FILE.includes(".config/openclawdreams"));
|
|
34
|
+
});
|
|
35
|
+
it("loads stored key from stable fallback when DATA_DIR is unset", async () => {
|
|
36
|
+
// Prepare fake credentials in the stable location
|
|
37
|
+
const configDir = join(fakeHome, ".config", "openclawdreams");
|
|
38
|
+
mkdirSync(configDir, { recursive: true });
|
|
39
|
+
const credsFile = join(configDir, "credentials.json");
|
|
40
|
+
writeFileSync(credsFile, JSON.stringify({ api_key: "fallback-key-123" }));
|
|
41
|
+
const client = new MoltbookClient();
|
|
42
|
+
globalThis.fetch = mockFetchJson({ status: "ok" });
|
|
43
|
+
await client.status();
|
|
44
|
+
const calls = globalThis.fetch.mock.calls;
|
|
45
|
+
const [, init] = calls[0].arguments;
|
|
46
|
+
const headers = init.headers;
|
|
47
|
+
assert.equal(headers["Authorization"], "Bearer fallback-key-123");
|
|
48
|
+
});
|
|
49
|
+
it("saves credentials to stable fallback when DATA_DIR is unset", async () => {
|
|
50
|
+
globalThis.fetch = mockFetchJson({
|
|
51
|
+
agent: {
|
|
52
|
+
api_key: "new-key-789",
|
|
53
|
+
claim_url: "https://moltbook.com/claim/xyz",
|
|
54
|
+
verification_code: "VERIFY789",
|
|
55
|
+
},
|
|
56
|
+
});
|
|
57
|
+
const client = new MoltbookClient("bootstrap-key");
|
|
58
|
+
await client.register("TestBot", "A test agent");
|
|
59
|
+
const credsFile = STABLE_CREDENTIALS_FILE;
|
|
60
|
+
assert.ok(existsSync(credsFile), "credentials file should be saved in stable location");
|
|
61
|
+
const creds = JSON.parse(readFileSync(credsFile, "utf-8"));
|
|
62
|
+
assert.equal(creds.api_key, "new-key-789");
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
//# sourceMappingURL=credentials_fallback.test.js.map
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import { describe, it, after, mock, beforeEach } from "node:test";
|
|
2
2
|
import assert from "node:assert/strict";
|
|
3
|
-
import { mkdtempSync, rmSync, existsSync, readFileSync } from "node:fs";
|
|
3
|
+
import { mkdtempSync, rmSync, existsSync, readFileSync, mkdirSync, writeFileSync, } from "node:fs";
|
|
4
4
|
import { join } from "node:path";
|
|
5
5
|
import { tmpdir } from "node:os";
|
|
6
6
|
// Isolated data dir
|
|
7
7
|
const testDir = mkdtempSync(join(tmpdir(), "es-moltbook-test-"));
|
|
8
8
|
process.env.OPENCLAWDREAMS_DATA_DIR = testDir;
|
|
9
|
+
// Isolated home dir
|
|
10
|
+
const fakeHome = mkdtempSync(join(tmpdir(), "es-moltbook-test-home-"));
|
|
11
|
+
process.env.HOME = fakeHome;
|
|
9
12
|
const { MoltbookClient } = await import("../src/moltbook.js");
|
|
10
13
|
const { CREDENTIALS_FILE } = await import("../src/config.js");
|
|
11
14
|
const { closeLogger } = await import("../src/logger.js");
|
|
@@ -156,9 +159,27 @@ describe("MoltbookClient", () => {
|
|
|
156
159
|
const headers = init.headers;
|
|
157
160
|
assert.equal(headers["Authorization"], "Bearer new-key-456");
|
|
158
161
|
});
|
|
162
|
+
it("loads from stable fallback if primary is missing when DATA_DIR IS set", async () => {
|
|
163
|
+
// 1. Delete primary credentials file if it exists
|
|
164
|
+
if (existsSync(CREDENTIALS_FILE))
|
|
165
|
+
rmSync(CREDENTIALS_FILE);
|
|
166
|
+
// 2. Prepare fake credentials in the stable location
|
|
167
|
+
mkdirSync(join(fakeHome, ".config", "openclawdreams"), { recursive: true });
|
|
168
|
+
const credsFile = join(fakeHome, ".config", "openclawdreams", "credentials.json");
|
|
169
|
+
writeFileSync(credsFile, JSON.stringify({ api_key: "cross-fallback-key-abc" }));
|
|
170
|
+
// 3. Client should load from stable path
|
|
171
|
+
const client = new MoltbookClient();
|
|
172
|
+
globalThis.fetch = mockFetchJson({ status: "ok" });
|
|
173
|
+
await client.status();
|
|
174
|
+
const calls = globalThis.fetch.mock.calls;
|
|
175
|
+
const [, init] = calls[0].arguments;
|
|
176
|
+
const headers = init.headers;
|
|
177
|
+
assert.equal(headers["Authorization"], "Bearer cross-fallback-key-abc");
|
|
178
|
+
});
|
|
159
179
|
});
|
|
160
180
|
after(async () => {
|
|
161
181
|
await closeLogger();
|
|
162
182
|
rmSync(testDir, { recursive: true, force: true, maxRetries: 3, retryDelay: 100 });
|
|
183
|
+
rmSync(fakeHome, { recursive: true, force: true, maxRetries: 3, retryDelay: 100 });
|
|
163
184
|
});
|
|
164
185
|
//# sourceMappingURL=moltbook.test.js.map
|
package/openclaw.plugin.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"id": "openclawdreams",
|
|
3
3
|
"name": "openclawdreams",
|
|
4
4
|
"displayName": "ElectricSheep",
|
|
5
|
-
"version": "1.5.
|
|
5
|
+
"version": "1.5.1",
|
|
6
6
|
"description": "A reflection engine that synthesizes agent-operator interactions into dreams, enriched by community and web context",
|
|
7
7
|
"entry": "dist/src/index.js",
|
|
8
8
|
"skills": [
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "openclawdreams",
|
|
3
|
-
"version": "1.5.
|
|
3
|
+
"version": "1.5.1",
|
|
4
4
|
"description": "A reflection engine that synthesizes agent-operator interactions into dreams",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"build": "tsc",
|
|
12
12
|
"dev": "tsc --watch",
|
|
13
13
|
"start": "node dist/bin/openclawdreams.js",
|
|
14
|
-
"test": "node --import tsx --test --test-concurrency=1 'test/**/*.test.ts'",
|
|
14
|
+
"test": "node --import tsx --test --test-isolation=process --test-concurrency=1 'test/**/*.test.ts'",
|
|
15
15
|
"lint": "eslint 'src/**/*.ts' 'test/**/*.ts' 'bin/**/*.ts'",
|
|
16
16
|
"lint:fix": "eslint --fix 'src/**/*.ts' 'test/**/*.ts' 'bin/**/*.ts'",
|
|
17
17
|
"format": "prettier --write 'src/**/*.ts' 'test/**/*.ts' 'bin/**/*.ts'",
|