@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.
- package/dist/hooks/guardrail-injector.d.ts +2 -0
- package/dist/hooks/guardrail-injector.js +37 -0
- package/dist/hooks/subagent-tracker.js +15 -1
- package/dist/index.js +6 -0
- package/dist/services/ralph-loop.js +0 -2
- package/dist/services/webhook-bridge.js +0 -2
- package/dist/types.d.ts +13 -4
- package/openclaw.plugin.json +1 -1
- package/package.json +1 -1
|
@@ -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
|
|
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
|
-
|
|
78
|
-
|
|
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;
|
package/openclaw.plugin.json
CHANGED
|
@@ -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.
|
|
5
|
+
"version": "0.18.0",
|
|
6
6
|
"skills": [
|
|
7
7
|
"skills"
|
|
8
8
|
],
|
package/package.json
CHANGED