@happycastle/oh-my-openclaw 0.9.1 → 0.10.0

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.
@@ -1,6 +1,6 @@
1
1
  import { OmocPluginApi } from '../types.js';
2
2
  export declare function resetPersonaInjectorState(): void;
3
3
  export declare function getPersonaInjectorState(): {
4
- lastPersonaInjectionTime: number;
4
+ lastInjectedPersonaId: string | null;
5
5
  };
6
6
  export declare function registerPersonaInjector(api: OmocPluginApi): void;
@@ -1,13 +1,11 @@
1
1
  import { getActivePersona } from '../utils/persona-state.js';
2
2
  import { readPersonaPromptSync } from '../agents/persona-prompts.js';
3
- /** Minimum interval (ms) between persona injections to prevent regurgitation. */
4
- const PERSONA_INJECTION_COOLDOWN_MS = 5_000;
5
- let lastPersonaInjectionTime = 0;
3
+ let lastInjectedPersonaId = null;
6
4
  export function resetPersonaInjectorState() {
7
- lastPersonaInjectionTime = 0;
5
+ lastInjectedPersonaId = null;
8
6
  }
9
7
  export function getPersonaInjectorState() {
10
- return { lastPersonaInjectionTime };
8
+ return { lastInjectedPersonaId };
11
9
  }
12
10
  export function registerPersonaInjector(api) {
13
11
  api.registerHook('agent:bootstrap', (event) => {
@@ -18,14 +16,11 @@ export function registerPersonaInjector(api) {
18
16
  if (!event.context.bootstrapFiles) {
19
17
  event.context.bootstrapFiles = [];
20
18
  }
21
- const alreadyInjected = event.context.bootstrapFiles.some((f) => f.path.startsWith('omoc://persona/'));
22
- if (alreadyInjected) {
23
- api.logger.info(`[omoc] Persona injection skipped (already present in bootstrapFiles)`);
19
+ const alreadyInFiles = event.context.bootstrapFiles.some((f) => f.path.startsWith('omoc://persona/'));
20
+ if (alreadyInFiles) {
24
21
  return;
25
22
  }
26
- const now = Date.now();
27
- if (now - lastPersonaInjectionTime < PERSONA_INJECTION_COOLDOWN_MS) {
28
- api.logger.info(`[omoc] Persona injection skipped (cooldown)`);
23
+ if (lastInjectedPersonaId === personaId) {
29
24
  return;
30
25
  }
31
26
  try {
@@ -34,7 +29,7 @@ export function registerPersonaInjector(api) {
34
29
  path: `omoc://persona/${personaId}`,
35
30
  content,
36
31
  });
37
- lastPersonaInjectionTime = now;
32
+ lastInjectedPersonaId = personaId;
38
33
  api.logger.info(`[omoc] Persona injected: ${personaId}`);
39
34
  }
40
35
  catch (err) {
@@ -42,6 +37,6 @@ export function registerPersonaInjector(api) {
42
37
  }
43
38
  }, {
44
39
  name: 'oh-my-openclaw.persona-injector',
45
- description: 'Injects active persona prompt into agent bootstrap (with dedup + cooldown)',
40
+ description: 'Injects active persona prompt once per persona change',
46
41
  });
47
42
  }
@@ -1,8 +1,6 @@
1
1
  import { OmocPluginApi } from '../types.js';
2
+ export type AgentRole = 'orchestrator' | 'worker' | 'lightweight';
3
+ export declare function classifyAgentRole(agentId?: string): AgentRole;
2
4
  export declare function resetEnforcerState(): void;
3
- export declare function getEnforcerState(): {
4
- lastInjectionTime: number;
5
- consecutiveFailures: number;
6
- disabledByFailures: boolean;
7
- };
5
+ export declare function getEnforcerState(): {};
8
6
  export declare function registerTodoEnforcer(api: OmocPluginApi): void;
@@ -1,28 +1,46 @@
1
1
  import { getConfig } from '../utils/config.js';
2
- const DIRECTIVE_TEXT = `[SYSTEM DIRECTIVE: OH-MY-OPENCLAW - TODO CONTINUATION]
3
- You MUST continue working on incomplete todos.
4
- - Do NOT stop until all tasks are marked complete
5
- - Do NOT ask for permission to continue
2
+ const ORCHESTRATOR_IDS = new Set([
3
+ 'omoc_prometheus',
4
+ 'omoc_atlas',
5
+ ]);
6
+ const WORKER_IDS = new Set([
7
+ 'omoc_sisyphus',
8
+ 'omoc_hephaestus',
9
+ 'omoc_frontend',
10
+ ]);
11
+ export function classifyAgentRole(agentId) {
12
+ if (!agentId)
13
+ return 'orchestrator';
14
+ if (ORCHESTRATOR_IDS.has(agentId))
15
+ return 'orchestrator';
16
+ if (WORKER_IDS.has(agentId))
17
+ return 'worker';
18
+ return 'lightweight';
19
+ }
20
+ const ORCHESTRATOR_DIRECTIVE = `[SYSTEM REMINDER - TODO CONTINUATION]
21
+ If you have incomplete todos, continue working on them.
6
22
  - Mark each task complete immediately when finished
7
23
  - If blocked, document the blocker and move to next task
24
+ - Do NOT restate prior messages — output only deltas and next concrete action
25
+ - If no actionable next step remains, declare tasks complete and stop
8
26
 
9
- [SUBAGENT COMPLETION RULE]
10
- When you receive a subagent completion notification ("✅ Subagent finished"):
11
- - This is an ACTION TRIGGER, not an FYI
12
- - IMMEDIATELY check the subagent's result
13
- - Verify against success criteria
14
- - Then proceed to the next task/phase
15
- - NEVER stop after receiving a completion notification`;
16
- let lastInjectionTime = 0;
17
- let consecutiveFailures = 0;
18
- let disabledByFailures = false;
27
+ When you receive a subagent completion notification:
28
+ - Check the subagent's result against success criteria
29
+ - Then proceed to the next task/phase`;
30
+ const WORKER_DIRECTIVE = `[SYSTEM REMINDER - TASK COMPLETION]
31
+ Complete your assigned task, return the result, then stop.
32
+ - Do NOT restate prior messages — output only new findings or changes
33
+ - If blocked, report the blocker and stop`;
34
+ const DIRECTIVES = {
35
+ orchestrator: ORCHESTRATOR_DIRECTIVE,
36
+ worker: WORKER_DIRECTIVE,
37
+ lightweight: null,
38
+ };
19
39
  export function resetEnforcerState() {
20
- lastInjectionTime = 0;
21
- consecutiveFailures = 0;
22
- disabledByFailures = false;
40
+ // no-op — kept for API compatibility (no global state to reset)
23
41
  }
24
42
  export function getEnforcerState() {
25
- return { lastInjectionTime, consecutiveFailures, disabledByFailures };
43
+ return {};
26
44
  }
27
45
  export function registerTodoEnforcer(api) {
28
46
  api.registerHook('agent:bootstrap', (event) => {
@@ -30,13 +48,9 @@ export function registerTodoEnforcer(api) {
30
48
  if (!config.todo_enforcer_enabled) {
31
49
  return;
32
50
  }
33
- if (disabledByFailures) {
34
- api.logger.warn('[omoc] Todo enforcer disabled due to consecutive failures');
35
- return;
36
- }
37
- const now = Date.now();
38
- if (config.todo_enforcer_cooldown_ms > 0 && (now - lastInjectionTime) < config.todo_enforcer_cooldown_ms) {
39
- api.logger.info('[omoc] Todo enforcer skipped (cooldown)');
51
+ const role = classifyAgentRole(event.context.agentId);
52
+ const directive = DIRECTIVES[role];
53
+ if (!directive) {
40
54
  return;
41
55
  }
42
56
  if (!event.context.bootstrapFiles) {
@@ -44,27 +58,20 @@ export function registerTodoEnforcer(api) {
44
58
  }
45
59
  const alreadyInjected = event.context.bootstrapFiles.some((f) => f.path === 'omoc://todo-enforcer');
46
60
  if (alreadyInjected) {
47
- api.logger.info('[omoc] Todo enforcer skipped (already present in bootstrapFiles)');
48
61
  return;
49
62
  }
50
63
  try {
51
64
  event.context.bootstrapFiles.push({
52
65
  path: 'omoc://todo-enforcer',
53
- content: DIRECTIVE_TEXT,
66
+ content: directive,
54
67
  });
55
- lastInjectionTime = now;
56
- consecutiveFailures = 0;
57
- api.logger.info('[omoc] Todo enforcer directive injected');
68
+ api.logger.info(`[omoc] Todo enforcer injected (role: ${role})`);
58
69
  }
59
- catch {
60
- consecutiveFailures++;
61
- if (config.todo_enforcer_max_failures > 0 && consecutiveFailures >= config.todo_enforcer_max_failures) {
62
- disabledByFailures = true;
63
- api.logger.error(`[omoc] Todo enforcer disabled after ${consecutiveFailures} consecutive failures`);
64
- }
70
+ catch (err) {
71
+ api.logger.error('[omoc] Todo enforcer injection failed:', err);
65
72
  }
66
73
  }, {
67
74
  name: 'oh-my-openclaw.todo-enforcer',
68
- description: 'Injects TODO continuation directive into agent bootstrap',
75
+ description: 'Injects role-aware TODO directive into agent bootstrap',
69
76
  });
70
77
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@happycastle/oh-my-openclaw",
3
- "version": "0.9.1",
3
+ "version": "0.10.0",
4
4
  "description": "Oh-My-OpenClaw plugin — multi-agent orchestration, todo enforcer, ralph loop, and custom tools for OpenClaw",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",