@happycastle/oh-my-openclaw 0.14.1 → 0.14.2
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/hooks/session-sync.js +5 -4
- package/dist/hooks/spawn-guard.js +2 -2
- package/dist/utils/config.js +6 -3
- package/dist/utils/paths.d.ts +6 -0
- package/dist/utils/paths.js +14 -0
- package/dist/utils/persona-state.d.ts +4 -4
- package/dist/utils/persona-state.js +22 -22
- package/package.json +1 -1
|
@@ -4,9 +4,10 @@ import { readPersonaPromptSync } from '../agents/persona-prompts.js';
|
|
|
4
4
|
import { readFileSync } from 'fs';
|
|
5
5
|
/** session_start hook: re-sync AGENTS.md from `.omoc-state` (source of truth). */
|
|
6
6
|
export function registerSessionSync(api) {
|
|
7
|
-
api.on('session_start', async (_event,
|
|
7
|
+
api.on('session_start', async (_event, ctx) => {
|
|
8
8
|
try {
|
|
9
|
-
const
|
|
9
|
+
const wsDir = ctx.workspaceDir;
|
|
10
|
+
const activePersona = await getActivePersona(wsDir);
|
|
10
11
|
if (!activePersona)
|
|
11
12
|
return;
|
|
12
13
|
const personaContent = readPersonaPromptSync(activePersona);
|
|
@@ -14,7 +15,7 @@ export function registerSessionSync(api) {
|
|
|
14
15
|
api.logger.warn(`${LOG_PREFIX} Session sync: persona file issue for ${activePersona}`);
|
|
15
16
|
return;
|
|
16
17
|
}
|
|
17
|
-
const agentsPath = resolveAgentsMdPath();
|
|
18
|
+
const agentsPath = resolveAgentsMdPath(wsDir);
|
|
18
19
|
try {
|
|
19
20
|
const current = readFileSync(agentsPath, 'utf-8');
|
|
20
21
|
if (current.includes(personaContent.slice(0, 100)))
|
|
@@ -23,7 +24,7 @@ export function registerSessionSync(api) {
|
|
|
23
24
|
catch {
|
|
24
25
|
// AGENTS.md missing or unreadable — needs sync
|
|
25
26
|
}
|
|
26
|
-
await replaceAgentsMd(personaContent);
|
|
27
|
+
await replaceAgentsMd(personaContent, wsDir);
|
|
27
28
|
api.logger.info(`${LOG_PREFIX} Session sync: AGENTS.md re-synced with .omoc-state (persona=${activePersona})`);
|
|
28
29
|
}
|
|
29
30
|
catch (err) {
|
|
@@ -5,13 +5,13 @@ const SPAWN_TOOL_NAME = 'sessions_spawn';
|
|
|
5
5
|
const AVAILABLE_AGENTS = ALL_AGENT_IDS.map((id) => id.replace('omoc_', '')).join(', ');
|
|
6
6
|
/** before_tool_call hook: block sessions_spawn without agentId when OmOC persona is active. */
|
|
7
7
|
export function registerSpawnGuard(api) {
|
|
8
|
-
api.on('before_tool_call', async (event,
|
|
8
|
+
api.on('before_tool_call', async (event, ctx) => {
|
|
9
9
|
if (event.toolName !== SPAWN_TOOL_NAME) {
|
|
10
10
|
return;
|
|
11
11
|
}
|
|
12
12
|
let activePersona;
|
|
13
13
|
try {
|
|
14
|
-
activePersona = await getActivePersona();
|
|
14
|
+
activePersona = await getActivePersona(ctx.workspaceDir);
|
|
15
15
|
}
|
|
16
16
|
catch {
|
|
17
17
|
return;
|
package/dist/utils/config.js
CHANGED
|
@@ -1,14 +1,17 @@
|
|
|
1
|
+
import { join } from 'path';
|
|
1
2
|
import { ABSOLUTE_MAX_RALPH_ITERATIONS } from '../types.js';
|
|
3
|
+
import { resolveOpenClawWorkspaceDir } from './paths.js';
|
|
2
4
|
export function getConfig(api) {
|
|
5
|
+
const wsDir = resolveOpenClawWorkspaceDir();
|
|
3
6
|
const defaults = {
|
|
4
7
|
max_ralph_iterations: 10,
|
|
5
8
|
todo_enforcer_enabled: false,
|
|
6
9
|
todo_enforcer_cooldown_ms: 2000,
|
|
7
10
|
todo_enforcer_max_failures: 5,
|
|
8
11
|
comment_checker_enabled: true,
|
|
9
|
-
notepad_dir: '
|
|
10
|
-
plans_dir: '
|
|
11
|
-
checkpoint_dir: '
|
|
12
|
+
notepad_dir: join(wsDir, 'notepads'),
|
|
13
|
+
plans_dir: join(wsDir, 'plans'),
|
|
14
|
+
checkpoint_dir: join(wsDir, 'checkpoints'),
|
|
12
15
|
tmux_socket: '/tmp/openclaw-tmux-sockets/openclaw.sock',
|
|
13
16
|
model_routing: undefined,
|
|
14
17
|
};
|
package/dist/utils/paths.d.ts
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
1
|
export declare const PLUGIN_ROOT: string;
|
|
2
2
|
export declare function resolvePluginPath(...segments: string[]): string;
|
|
3
3
|
export declare function resolveWorkspacePath(workspaceDir: string, ...segments: string[]): string;
|
|
4
|
+
/**
|
|
5
|
+
* Resolve the OpenClaw workspace directory (absolute path).
|
|
6
|
+
* Uses explicit workspaceDir when provided (e.g. from hook context),
|
|
7
|
+
* otherwise falls back to ~/.openclaw/workspace with OPENCLAW_PROFILE support.
|
|
8
|
+
*/
|
|
9
|
+
export declare function resolveOpenClawWorkspaceDir(workspaceDir?: string): string;
|
package/dist/utils/paths.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { fileURLToPath } from 'url';
|
|
2
2
|
import { dirname, join, resolve } from 'path';
|
|
3
|
+
import { homedir } from 'os';
|
|
3
4
|
const __filename = fileURLToPath(import.meta.url);
|
|
4
5
|
const __dirname = dirname(__filename);
|
|
5
6
|
// Resolves to plugin root (from dist/utils/ → go up ../../)
|
|
@@ -11,3 +12,16 @@ export function resolvePluginPath(...segments) {
|
|
|
11
12
|
export function resolveWorkspacePath(workspaceDir, ...segments) {
|
|
12
13
|
return join(workspaceDir, ...segments);
|
|
13
14
|
}
|
|
15
|
+
/**
|
|
16
|
+
* Resolve the OpenClaw workspace directory (absolute path).
|
|
17
|
+
* Uses explicit workspaceDir when provided (e.g. from hook context),
|
|
18
|
+
* otherwise falls back to ~/.openclaw/workspace with OPENCLAW_PROFILE support.
|
|
19
|
+
*/
|
|
20
|
+
export function resolveOpenClawWorkspaceDir(workspaceDir) {
|
|
21
|
+
if (workspaceDir)
|
|
22
|
+
return workspaceDir;
|
|
23
|
+
const profile = process.env.OPENCLAW_PROFILE?.trim();
|
|
24
|
+
return (profile && profile.toLowerCase() !== 'default')
|
|
25
|
+
? join(homedir(), '.openclaw', `workspace-${profile}`)
|
|
26
|
+
: join(homedir(), '.openclaw', 'workspace');
|
|
27
|
+
}
|
|
@@ -2,9 +2,9 @@ import type { OmocPluginApi } from '../types.js';
|
|
|
2
2
|
export declare function initPersonaState(_api: OmocPluginApi): Promise<void>;
|
|
3
3
|
export declare function setActivePersonaId(id: string | null): Promise<void>;
|
|
4
4
|
export declare function setActivePersona(id: string | null): Promise<void>;
|
|
5
|
-
export declare function getActivePersona(): Promise<string | null>;
|
|
5
|
+
export declare function getActivePersona(workspaceDir?: string): Promise<string | null>;
|
|
6
6
|
export declare function resetPersonaState(): Promise<void>;
|
|
7
7
|
export declare const OFF_MARKER = "__OFF__";
|
|
8
|
-
export declare function resolveAgentsMdPath(): string;
|
|
9
|
-
export declare function replaceAgentsMd(personaContent: string): Promise<void>;
|
|
10
|
-
export declare function restoreAgentsMdToDefault(): Promise<void>;
|
|
8
|
+
export declare function resolveAgentsMdPath(workspaceDir?: string): string;
|
|
9
|
+
export declare function replaceAgentsMd(personaContent: string, workspaceDir?: string): Promise<void>;
|
|
10
|
+
export declare function restoreAgentsMdToDefault(workspaceDir?: string): Promise<void>;
|
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
import { readFile, writeFile, mkdir } from 'fs/promises';
|
|
2
2
|
import { dirname, join } from 'path';
|
|
3
|
-
import {
|
|
3
|
+
import { resolveOpenClawWorkspaceDir } from './paths.js';
|
|
4
4
|
let activePersonaId = null;
|
|
5
5
|
let loaded = false;
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
function resolveStateDir(workspaceDir) {
|
|
7
|
+
return join(resolveOpenClawWorkspaceDir(workspaceDir), '.omoc-state');
|
|
8
|
+
}
|
|
9
|
+
function resolveStateFilePath(workspaceDir) {
|
|
10
|
+
return join(resolveStateDir(workspaceDir), 'active-persona');
|
|
11
|
+
}
|
|
8
12
|
export async function initPersonaState(_api) {
|
|
9
13
|
try {
|
|
10
|
-
await mkdir(
|
|
14
|
+
await mkdir(resolveStateDir(), { recursive: true });
|
|
11
15
|
}
|
|
12
16
|
catch (error) {
|
|
13
17
|
console.warn('[omoc] Failed to initialize persona state directory:', error);
|
|
@@ -22,9 +26,9 @@ export async function setActivePersonaId(id) {
|
|
|
22
26
|
export async function setActivePersona(id) {
|
|
23
27
|
await setActivePersonaId(id);
|
|
24
28
|
}
|
|
25
|
-
export async function getActivePersona() {
|
|
29
|
+
export async function getActivePersona(workspaceDir) {
|
|
26
30
|
if (!loaded)
|
|
27
|
-
await loadFromDisk();
|
|
31
|
+
await loadFromDisk(workspaceDir);
|
|
28
32
|
return activePersonaId;
|
|
29
33
|
}
|
|
30
34
|
export async function resetPersonaState() {
|
|
@@ -32,9 +36,9 @@ export async function resetPersonaState() {
|
|
|
32
36
|
loaded = true;
|
|
33
37
|
await saveOffState();
|
|
34
38
|
}
|
|
35
|
-
async function loadFromDisk() {
|
|
39
|
+
async function loadFromDisk(workspaceDir) {
|
|
36
40
|
try {
|
|
37
|
-
const content = (await readFile(
|
|
41
|
+
const content = (await readFile(resolveStateFilePath(workspaceDir), 'utf-8')).trim();
|
|
38
42
|
activePersonaId = (content && content !== OFF_MARKER) ? content : null;
|
|
39
43
|
}
|
|
40
44
|
catch (error) {
|
|
@@ -49,8 +53,8 @@ async function loadFromDisk() {
|
|
|
49
53
|
export const OFF_MARKER = '__OFF__';
|
|
50
54
|
async function saveToDisk() {
|
|
51
55
|
try {
|
|
52
|
-
await mkdir(
|
|
53
|
-
await writeFile(
|
|
56
|
+
await mkdir(resolveStateDir(), { recursive: true });
|
|
57
|
+
await writeFile(resolveStateFilePath(), activePersonaId ?? '', 'utf-8');
|
|
54
58
|
}
|
|
55
59
|
catch (error) {
|
|
56
60
|
console.warn('[omoc] Failed to persist persona state to disk:', error);
|
|
@@ -58,28 +62,24 @@ async function saveToDisk() {
|
|
|
58
62
|
}
|
|
59
63
|
async function saveOffState() {
|
|
60
64
|
try {
|
|
61
|
-
await mkdir(
|
|
62
|
-
await writeFile(
|
|
65
|
+
await mkdir(resolveStateDir(), { recursive: true });
|
|
66
|
+
await writeFile(resolveStateFilePath(), OFF_MARKER, 'utf-8');
|
|
63
67
|
}
|
|
64
68
|
catch (error) {
|
|
65
69
|
console.warn('[omoc] Failed to persist persona off-state to disk:', error);
|
|
66
70
|
}
|
|
67
71
|
}
|
|
68
|
-
export function resolveAgentsMdPath() {
|
|
69
|
-
|
|
70
|
-
const wsDir = (profile && profile.toLowerCase() !== 'default')
|
|
71
|
-
? join(homedir(), '.openclaw', `workspace-${profile}`)
|
|
72
|
-
: join(homedir(), '.openclaw', 'workspace');
|
|
73
|
-
return join(wsDir, 'AGENTS.md');
|
|
72
|
+
export function resolveAgentsMdPath(workspaceDir) {
|
|
73
|
+
return join(resolveOpenClawWorkspaceDir(workspaceDir), 'AGENTS.md');
|
|
74
74
|
}
|
|
75
|
-
export async function replaceAgentsMd(personaContent) {
|
|
76
|
-
const agentsPath = resolveAgentsMdPath();
|
|
75
|
+
export async function replaceAgentsMd(personaContent, workspaceDir) {
|
|
76
|
+
const agentsPath = resolveAgentsMdPath(workspaceDir);
|
|
77
77
|
await mkdir(dirname(agentsPath), { recursive: true });
|
|
78
78
|
const merged = `${DEFAULT_AGENTS_MD}\n---\n\n${personaContent}`;
|
|
79
79
|
await writeFile(agentsPath, merged, 'utf-8');
|
|
80
80
|
}
|
|
81
|
-
export async function restoreAgentsMdToDefault() {
|
|
82
|
-
const agentsPath = resolveAgentsMdPath();
|
|
81
|
+
export async function restoreAgentsMdToDefault(workspaceDir) {
|
|
82
|
+
const agentsPath = resolveAgentsMdPath(workspaceDir);
|
|
83
83
|
await mkdir(dirname(agentsPath), { recursive: true });
|
|
84
84
|
await writeFile(agentsPath, DEFAULT_AGENTS_MD, 'utf-8');
|
|
85
85
|
}
|
package/package.json
CHANGED