fix: capture dispatch-stage prompt
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
Minimal OpenClaw plugin that mirrors Claude Code's `capture_stop.py` behavior:
|
||||
|
||||
- watches user-triggered assistant turns
|
||||
- uses OpenClaw's cleaned user message (`before_agent_reply.cleanedBody`) so AtoCore stores the real prompt instead of the full inbound wrapper
|
||||
- uses OpenClaw's dispatch-stage message body (`before_dispatch.body`) so AtoCore stores the real prompt instead of the full inbound wrapper
|
||||
- POSTs `prompt` + `response` to `POST /interactions`
|
||||
- sets `client="openclaw"`
|
||||
- sets `reinforce=true`
|
||||
@@ -26,6 +26,6 @@ If `baseUrl` is omitted, the plugin uses `ATOCORE_BASE_URL` or defaults to `http
|
||||
## Notes
|
||||
|
||||
- Project detection is intentionally left empty for now. Unscoped capture is acceptable because AtoCore's extraction pipeline handles unscoped interactions.
|
||||
- Prompt cleaning is done inside the plugin by reading OpenClaw's finalized cleaned message body instead of the raw prompt-build input.
|
||||
- Prompt cleaning is done inside the plugin by reading OpenClaw's dispatch-stage message body instead of the raw prompt-build input.
|
||||
- Extraction is **not** part of the capture path. This plugin only records interactions and lets AtoCore reinforcement run automatically.
|
||||
- The plugin captures only user-triggered turns, not heartbeats or system-only runs.
|
||||
|
||||
@@ -46,26 +46,28 @@ export default definePluginEntry({
|
||||
const logger = api.logger;
|
||||
const pendingBySession = new Map();
|
||||
|
||||
api.on("before_agent_reply", async (event, ctx) => {
|
||||
if (ctx?.trigger && ctx.trigger !== "user") return;
|
||||
api.on("before_dispatch", async (event, ctx) => {
|
||||
const config = api.getConfig?.() || {};
|
||||
const minPromptLength = Number(config.minPromptLength || DEFAULT_MIN_PROMPT_LENGTH);
|
||||
const prompt = trimText(event?.cleanedBody || "");
|
||||
const prompt = trimText(event?.body || event?.content || "");
|
||||
const key = ctx?.sessionKey || event?.sessionKey;
|
||||
if (!key) return;
|
||||
if (!shouldCapturePrompt(prompt, minPromptLength)) {
|
||||
pendingBySession.delete(ctx.sessionId);
|
||||
pendingBySession.delete(key);
|
||||
return;
|
||||
}
|
||||
pendingBySession.set(ctx.sessionId, {
|
||||
pendingBySession.set(key, {
|
||||
prompt,
|
||||
sessionId: ctx.sessionId,
|
||||
sessionKey: ctx.sessionKey || "",
|
||||
sessionId: key,
|
||||
sessionKey: key,
|
||||
project: ""
|
||||
});
|
||||
});
|
||||
|
||||
api.on("llm_output", async (event, ctx) => {
|
||||
if (ctx?.trigger && ctx.trigger !== "user") return;
|
||||
const pending = pendingBySession.get(ctx.sessionId);
|
||||
const key = ctx.sessionKey || ctx.sessionId;
|
||||
const pending = pendingBySession.get(key);
|
||||
if (!pending) return;
|
||||
|
||||
const assistantTexts = Array.isArray(event?.assistantTexts) ? event.assistantTexts : [];
|
||||
@@ -87,15 +89,17 @@ export default definePluginEntry({
|
||||
};
|
||||
|
||||
await postInteraction(baseUrl, payload, logger);
|
||||
pendingBySession.delete(ctx.sessionId);
|
||||
pendingBySession.delete(key);
|
||||
});
|
||||
|
||||
api.on("agent_end", async (event) => {
|
||||
if (event?.sessionId) pendingBySession.delete(event.sessionId);
|
||||
const key = event?.sessionKey || event?.sessionId;
|
||||
if (key) pendingBySession.delete(key);
|
||||
});
|
||||
|
||||
api.on("session_end", async (event) => {
|
||||
if (event?.sessionId) pendingBySession.delete(event.sessionId);
|
||||
const key = event?.sessionKey || event?.sessionId;
|
||||
if (key) pendingBySession.delete(key);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user