Files
zn-ai/build/preinstalled-skills/self-improving-agent/hooks/openclaw/handler.js
duanshuwen 38bea97197 feat: Enhance Marketplace and Skill Management UI with improved error handling and user feedback
- Updated MarketplaceDrawer to include security notes and manual installation hints.
- Refactored SkillDetailDrawer to display default icons for skills.
- Simplified SkillListItem to use default icons for better readability.
- Integrated gateway status checks and warnings in SkillsPage for improved user awareness.
- Enhanced error handling for skill installation and fetching, providing clearer feedback to users.
- Added new translations for error messages and gateway warnings to improve localization support.
2026-04-19 20:33:44 +08:00

113 lines
3.3 KiB
JavaScript

/**
* Self-Improvement Hook for OpenClaw
*
* Injects a reminder to evaluate learnings during agent bootstrap.
* Fires on agent:bootstrap event before workspace files are injected.
*/
const REMINDER_NAME = 'SELF_IMPROVEMENT_REMINDER.md';
const REMINDER_PATH = REMINDER_NAME;
const REMINDER_CONTENT = `
## Self-Improvement Reminder
After completing tasks, evaluate whether any learnings should be captured.
Only log if this repo or workspace is using the self-improvement skill.
Before logging:
- Create only missing \`.learnings/\` files; never overwrite existing content
- Do not log secrets, tokens, private keys, environment variables, or raw transcripts
- Prefer short summaries or redacted excerpts over full command output
**Log when:**
- User corrects you → \`.learnings/LEARNINGS.md\`
- Command/operation fails → \`.learnings/ERRORS.md\`
- User wants missing capability → \`.learnings/FEATURE_REQUESTS.md\`
- You discover your knowledge was wrong → \`.learnings/LEARNINGS.md\`
- You find a better approach → \`.learnings/LEARNINGS.md\`
**Promote when pattern is proven:**
- Behavioral patterns → \`SOUL.md\`
- Workflow improvements → \`AGENTS.md\`
- Tool gotchas → \`TOOLS.md\`
Keep entries simple: date, title, what happened, and what to do differently.
`.trim();
function isObject(value) {
return !!value && typeof value === 'object';
}
function isInjectedReminderFile(value) {
if (!isObject(value) || value.path !== REMINDER_PATH) {
return false;
}
return (
value.virtual === true ||
value.content === REMINDER_CONTENT
);
}
const handler = async (event) => {
// Safety checks for event structure
if (!event || typeof event !== 'object') {
return;
}
// Only handle agent:bootstrap events
if (event.type !== 'agent' || event.action !== 'bootstrap') {
return;
}
// Safety check for context
if (!event.context || typeof event.context !== 'object') {
return;
}
// Skip sub-agent sessions to avoid bootstrap issues
// Sub-agents have sessionKey patterns like "agent:main:subagent:..."
const sessionKey = event.sessionKey || '';
if (sessionKey.includes(':subagent:')) {
return;
}
// Inject the reminder as a virtual bootstrap file
// Check that bootstrapFiles is an array before pushing
if (Array.isArray(event.context.bootstrapFiles)) {
const occupiedByOtherFile = event.context.bootstrapFiles.some(
(file) => isObject(file) && file.path === REMINDER_PATH && !isInjectedReminderFile(file),
);
if (occupiedByOtherFile) {
return;
}
const cleanedBootstrapFiles = event.context.bootstrapFiles.filter(
(file, index, files) =>
!isInjectedReminderFile(file) ||
files.findIndex((candidate) => isInjectedReminderFile(candidate)) === index,
);
const reminderFile = {
name: REMINDER_NAME,
path: REMINDER_PATH,
content: REMINDER_CONTENT,
missing: false,
virtual: true,
};
const existingIndex = cleanedBootstrapFiles.findIndex((file) => isInjectedReminderFile(file));
if (existingIndex === -1) {
cleanedBootstrapFiles.push(reminderFile);
} else {
cleanedBootstrapFiles[existingIndex] = reminderFile;
}
event.context.bootstrapFiles = cleanedBootstrapFiles;
}
};
module.exports = handler;
module.exports.default = handler;