@happycastle/oh-my-openclaw 0.17.0 → 0.18.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.
@@ -0,0 +1,2 @@
1
+ import { OmocPluginApi } from '../types.js';
2
+ export declare function registerGuardrailInjector(api: OmocPluginApi): void;
@@ -0,0 +1,37 @@
1
+ import { LOG_PREFIX } from '../constants.js';
2
+ const GUARDRAIL_RULES = `
3
+ <anti-hallucination-guardrails>
4
+ ## Anti-Hallucination Rules (MANDATORY)
5
+
6
+ These rules are NON-NEGOTIABLE. Violating them is a critical failure.
7
+
8
+ ### Rule 1: No Fake Tool Calls
9
+ - If you say "I read the file", "I checked the code", "I confirmed in the source", or similar — there MUST be a corresponding \`read\`, \`exec\`, \`grep\`, or equivalent tool call in THE SAME turn.
10
+ - If you did NOT make a tool call, you MUST say: "I haven't verified this directly — this is based on my prior knowledge/context."
11
+ - Phrases that REQUIRE a preceding tool call: "확인했다", "읽었다", "봤다", "코드에서", "소스를 보면", "파일을 열어보니", "checked", "verified", "confirmed", "read the file", "looked at the code"
12
+
13
+ ### Rule 2: No Fabricated Results
14
+ - Never invent file contents, command outputs, or API responses.
15
+ - If you're unsure what a file contains, READ IT. Don't guess.
16
+ - If a tool call fails, report the failure — don't make up what the result "would have been."
17
+
18
+ ### Rule 3: Distinguish Memory from Verification
19
+ - Information from previous sessions or context = "이전 세션 기억 기반으로는..." or "Based on prior context..."
20
+ - Information from THIS session's tool calls = state it directly
21
+ - NEVER present memory/context as if you just verified it with a tool call.
22
+
23
+ ### Rule 4: Sub-agent Delegation Honesty
24
+ - If asked to delegate to a sub-agent, you MUST actually call \`sessions_spawn\` or \`omoc_delegate\`.
25
+ - Saying "서브에이전트 호출 완료" without a tool call = CRITICAL VIOLATION.
26
+ - If the spawn fails, report the failure honestly.
27
+ </anti-hallucination-guardrails>
28
+ `.trim();
29
+ export function registerGuardrailInjector(api) {
30
+ api.on('before_prompt_build', (_event, _ctx) => {
31
+ api.logger.info(`${LOG_PREFIX} Guardrail rules injected via before_prompt_build`);
32
+ return {
33
+ prependContext: GUARDRAIL_RULES,
34
+ };
35
+ }, { priority: 90 } // Between persona (100) and context-injector (50)
36
+ );
37
+ }
@@ -1,5 +1,7 @@
1
1
  import { LOG_PREFIX } from '../constants.js';
2
2
  import { trackSubagentSpawn, clearSubagentTracking } from '../services/webhook-bridge.js';
3
+ import { callHooksWake } from '../utils/webhook-client.js';
4
+ import { getConfig } from '../utils/config.js';
3
5
  const SPAWN_TOOL_NAME = 'sessions_spawn';
4
6
  function extractSpawnResult(content) {
5
7
  try {
@@ -52,11 +54,23 @@ export function registerSubagentTracker(api) {
52
54
  if (runIdMatch) {
53
55
  clearSubagentTracking(runIdMatch[1]);
54
56
  api.logger.info(`${LOG_PREFIX} Cleared sub-agent tracking: runId=${runIdMatch[1]} (announce received)`);
57
+ // Send wake to ensure the main agent processes the announce and continues work
58
+ const config = getConfig(api);
59
+ if (config.webhook_bridge_enabled && config.gateway_url && config.hooks_token) {
60
+ void callHooksWake(`[System] Sub-agent completed (runId=${runIdMatch[1]}). Process the announce result and continue any pending work.`, { gateway_url: config.gateway_url, hooks_token: config.hooks_token }, api.logger).then((result) => {
61
+ if (result.ok) {
62
+ api.logger.info(`${LOG_PREFIX} Wake sent after sub-agent announce: runId=${runIdMatch[1]}`);
63
+ }
64
+ else {
65
+ api.logger.warn(`${LOG_PREFIX} Wake after announce failed: ${result.error ?? `status ${result.status}`}`);
66
+ }
67
+ });
68
+ }
55
69
  }
56
70
  return undefined;
57
71
  }, {
58
72
  name: 'oh-my-openclaw.subagent-announce-detector',
59
- description: 'Detects sub-agent announce messages and clears stale tracking',
73
+ description: 'Detects sub-agent announce messages, clears stale tracking, and wakes main agent',
60
74
  });
61
75
  }
62
76
  export { extractSpawnResult };
package/dist/index.js CHANGED
@@ -18,6 +18,7 @@ import { registerRalphCommands } from './commands/ralph-commands.js';
18
18
  import { registerStatusCommands } from './commands/status-commands.js';
19
19
  import { registerPersonaCommands } from './commands/persona-commands.js';
20
20
  import { registerContextInjector } from './hooks/context-injector.js';
21
+ import { registerGuardrailInjector } from './hooks/guardrail-injector.js';
21
22
  import { registerSessionSync } from './hooks/session-sync.js';
22
23
  import { registerSpawnGuard } from './hooks/spawn-guard.js';
23
24
  import { registerKeywordDetector } from './hooks/keyword-detector/hook.js';
@@ -95,6 +96,11 @@ export default function register(api) {
95
96
  registry.hooks.push('context-injector');
96
97
  api.logger.info(`[${PLUGIN_ID}] Context injector hook registered (before_prompt_build)`);
97
98
  });
99
+ safeRegister(api, 'guardrail-injector', 'hook', () => {
100
+ registerGuardrailInjector(guarded);
101
+ registry.hooks.push('guardrail-injector');
102
+ api.logger.info(`[${PLUGIN_ID}] Guardrail injector hook registered (before_prompt_build, priority 90)`);
103
+ });
98
104
  safeRegister(api, 'session-sync', 'hook', () => {
99
105
  registerSessionSync(api);
100
106
  registry.hooks.push('session-sync');
@@ -62,8 +62,6 @@ export function registerRalphLoop(api) {
62
62
  stateFilePath = join(config.checkpoint_dir, 'ralph-loop-state.json');
63
63
  api.registerService({
64
64
  id: 'omoc-ralph-loop',
65
- name: 'Ralph Loop Service',
66
- description: 'Self-referential completion mechanism with configurable iterations',
67
65
  start: async () => {
68
66
  await loadStateFromFile();
69
67
  },
@@ -86,8 +86,6 @@ export function registerWebhookBridge(api) {
86
86
  const config = getConfig(api);
87
87
  api.registerService({
88
88
  id: 'omoc-webhook-bridge',
89
- name: 'Webhook Bridge Service',
90
- description: 'Proactive agent messaging via Gateway webhook hooks',
91
89
  start: async () => {
92
90
  if (!config.webhook_bridge_enabled) {
93
91
  api.logger.info(`${LOG_PREFIX} Webhook bridge disabled (set webhook_bridge_enabled: true to enable)`);
package/dist/types.d.ts CHANGED
@@ -72,12 +72,21 @@ export interface CommandRegistration<TCtx = {
72
72
  text: string;
73
73
  }>;
74
74
  }
75
+ export interface ServiceContext {
76
+ config: unknown;
77
+ workspaceDir?: string;
78
+ stateDir: string;
79
+ logger: {
80
+ info: (message: string) => void;
81
+ warn: (message: string) => void;
82
+ error: (message: string) => void;
83
+ debug?: (message: string) => void;
84
+ };
85
+ }
75
86
  export interface ServiceRegistration {
76
87
  id: string;
77
- name: string;
78
- description?: string;
79
- start?: () => Promise<void>;
80
- stop?: () => Promise<void>;
88
+ start: (ctx: ServiceContext) => void | Promise<void>;
89
+ stop?: (ctx: ServiceContext) => void | Promise<void>;
81
90
  }
82
91
  export interface OmocPluginApi {
83
92
  pluginConfig?: PluginConfig;
@@ -2,7 +2,7 @@
2
2
  "id": "oh-my-openclaw",
3
3
  "name": "Oh-My-OpenClaw",
4
4
  "description": "Multi-agent orchestration plugin — 11 agents, category-based model routing, todo enforcer, ralph loop, agent setup CLI, and custom tools",
5
- "version": "0.17.0",
5
+ "version": "0.18.0",
6
6
  "skills": [
7
7
  "skills"
8
8
  ],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@happycastle/oh-my-openclaw",
3
- "version": "0.17.0",
3
+ "version": "0.18.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",