feat: implement OpenClaw integration
Ports the OMX OpenClaw module into oh-my-openagent as a first-class integration. This integration allows forwarding internal events (session lifecycle, tool execution) to external gateways (HTTP or command-based). - Added `src/openclaw` directory with implementation: - `dispatcher.ts`: Handles HTTP/Command dispatching with interpolation - `types.ts`: TypeScript definitions - `client.ts`: Main entry point `wakeOpenClaw` - `index.ts`: Public API - Added `src/config/schema/openclaw.ts` for Zod schema validation - Updated `src/config/schema/oh-my-opencode-config.ts` to include `openclaw` config - Added `src/hooks/openclaw-sender/index.ts` to listen for events - Registered the hook in `src/plugin/hooks/create-session-hooks.ts` - Added unit tests in `src/openclaw/__tests__` Events handled: - `session-start` (via `session.created`) - `session-end` (via `session.deleted`) - `session-idle` (via `session.idle`) - `ask-user-question` (via `tool.execute.before` for `ask_user_question`) - `stop` (via `tool.execute.before` for `stop-continuation` command)
This commit is contained in:
@@ -0,0 +1,66 @@
|
||||
import { wakeOpenClaw } from "../../openclaw/client";
|
||||
import type { OpenClawConfig, OpenClawContext } from "../../openclaw/types";
|
||||
import { getMainSessionID } from "../../features/claude-code-session-state";
|
||||
import type { PluginContext } from "../../plugin/types";
|
||||
|
||||
export function createOpenClawSenderHook(
|
||||
ctx: PluginContext,
|
||||
config: OpenClawConfig
|
||||
) {
|
||||
return {
|
||||
event: async (input: {
|
||||
event: { type: string; properties?: Record<string, unknown> };
|
||||
}) => {
|
||||
const { type, properties } = input.event;
|
||||
const context: OpenClawContext = {
|
||||
sessionId: (properties?.sessionID as string) || getMainSessionID(),
|
||||
projectPath: ctx.directory,
|
||||
};
|
||||
|
||||
if (type === "session.created") {
|
||||
await wakeOpenClaw("session-start", context, config);
|
||||
} else if (type === "session.idle") {
|
||||
await wakeOpenClaw("session-idle", context, config);
|
||||
} else if (type === "session.deleted") {
|
||||
await wakeOpenClaw("session-end", context, config);
|
||||
}
|
||||
},
|
||||
|
||||
"tool.execute.before": async (
|
||||
input: { tool: string; sessionID: string },
|
||||
output: { args: Record<string, unknown> }
|
||||
) => {
|
||||
const toolName = input.tool.toLowerCase();
|
||||
const context: OpenClawContext = {
|
||||
sessionId: input.sessionID,
|
||||
projectPath: ctx.directory,
|
||||
};
|
||||
|
||||
if (
|
||||
toolName === "ask_user_question" ||
|
||||
toolName === "askuserquestion" ||
|
||||
toolName === "question"
|
||||
) {
|
||||
const question =
|
||||
typeof output.args.question === "string"
|
||||
? output.args.question
|
||||
: undefined;
|
||||
await wakeOpenClaw(
|
||||
"ask-user-question",
|
||||
{
|
||||
...context,
|
||||
question,
|
||||
},
|
||||
config
|
||||
);
|
||||
} else if (toolName === "skill") {
|
||||
const rawName =
|
||||
typeof output.args.name === "string" ? output.args.name : undefined;
|
||||
const command = rawName?.replace(/^\//, "").toLowerCase();
|
||||
if (command === "stop-continuation") {
|
||||
await wakeOpenClaw("stop", context, config);
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user