diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 000000000..acf4d0c60 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,315 @@ +# Pull Request: [Title] + + + +## ๐Ÿ“‹ Summary + + + +## ๐ŸŽฏ Related Issues + + + +Closes # + +## ๐Ÿš€ What's New + + + +### Core Changes + +#### 1. [Feature/Component Name] + +**Purpose**: [Why this change was made] + +**Implementation**: + +- Change 1 +- Change 2 +- Change 3 + +**Key Code** (if applicable): + +```javascript +// Show important code snippets with file paths +// /path/to/file.js:123-145 +``` + +## ๐Ÿ“Š Type of Change + + + +- [ ] ๐Ÿ› Bug fix (non-breaking change that fixes an issue) +- [ ] โœจ New feature (non-breaking change that adds functionality) +- [ ] ๐Ÿ’ฅ Breaking change (fix or feature that would cause existing functionality to change) +- [ ] ๐Ÿ“ Documentation update +- [ ] ๐Ÿ”ง Configuration change +- [ ] โ™ป๏ธ Code refactoring (no functional changes) +- [ ] โšก Performance improvement +- [ ] ๐ŸŽจ UI/UX change +- [ ] ๐Ÿงช Test coverage improvement +- [ ] ๐Ÿ”’ Security fix + +## ๐Ÿงช Testing + + + +### Automated Tests + +- [ ] Unit tests added/updated +- [ ] Integration tests added/updated +- [ ] All existing tests pass + +**Test Coverage**: + +- [ ] New code has test coverage +- [ ] Edge cases covered +- [ ] Error handling tested + +**Test Results**: + +```bash +# Include test output or summary +โœ“ 42 tests passing +โœ“ 0 tests failing +``` + +### Manual Testing + + + +**Testing Checklist**: + +- [ ] Tested in development environment +- [ ] Tested in staging environment (if applicable) +- [ ] Tested with real data/production-like scenarios +- [ ] Tested error scenarios +- [ ] Verified no console errors/warnings +- [ ] Checked browser console for issues (frontend changes) + +**Environments Tested**: + +- [ ] Development +- [ ] Staging +- [ ] Production (if safe to test) + +## ๐Ÿ“ธ Screenshots/Videos + + + +### Before + + + +### After + + + +## ๐Ÿš€ Deployment Strategy + + + +### Deployment Steps + +1. Step 1 +2. Step 2 +3. Step 3 + +### Configuration Changes + + + +- [ ] Environment variables added/updated: `VARIABLE_NAME=value` +- [ ] Feature flags required: `FEATURE_FLAG=true` +- [ ] Database migrations needed +- [ ] External service configuration required + +### Phased Rollout (if applicable) + +- [ ] **Phase 1**: Deploy to staging for validation (recommended duration: X days) +- [ ] **Phase 2**: Deploy to production with feature flag disabled +- [ ] **Phase 3**: Enable feature flag for production traffic +- [ ] **Phase 4**: Monitor metrics and remove feature flag + +## ๐Ÿ”™ Rollback Plan + + + +**Quick Rollback**: + +- Disable feature flag: `FEATURE_FLAG=false` and restart service (< 1 minute) +- OR: Revert to previous deployment revision +- OR: Git revert commit hash + +**Cleanup Required** (if rollback is performed): + +- [ ] Database changes to revert +- [ ] Cache to clear +- [ ] External services to notify + +## ๐Ÿ’ฐ Cost Impact + + + +**Expected Cost Changes**: + +- Cloud Run: +/- $X/month +- Storage: +/- $X/month +- API calls: +/- $X/month +- **Total Estimated Impact**: +/- $X/month + +**Cost Optimization Notes**: + +- [Explain any cost optimizations included] + +## โšก Performance Impact + + + +**Expected Performance Changes**: + +- Response time: +/- Xms +- Memory usage: +/- XMB +- Database queries: +/- X queries +- API calls: +/- X calls + +**Benchmarks** (if applicable): + +```text +Before: Xms average response time +After: Xms average response time +``` + +## ๐Ÿ” Code Quality + + + +- [x] ESLint passed (auto-checked by pre-commit hooks) +- [x] Prettier formatting applied (auto-checked by pre-commit hooks) +- [x] Markdownlint passed for docs (auto-checked by pre-commit hooks) +- [x] Commit messages follow conventional commits +- [ ] Code reviewed by AI agent or peer +- [ ] No console.log statements in production code +- [ ] No commented-out code left behind +- [ ] Error handling implemented for edge cases +- [ ] Security considerations reviewed (XSS, SQL injection, auth, etc.) + +## ๐Ÿ“š Documentation + + + +- [ ] README.md updated (if user-facing changes) +- [ ] CONTRIBUTING.md updated (if dev workflow changes) +- [ ] API documentation updated (if API changes) +- [ ] Inline code comments added for complex logic +- [ ] Architecture documentation updated (if structural changes) +- [ ] CLAUDE.md updated (for AI context in future sessions) + +## ๐Ÿ” Security Considerations + + + +- [ ] No sensitive data logged or exposed +- [ ] Authentication/authorization implemented correctly +- [ ] Input validation added for user input +- [ ] SQL injection prevention (parameterized queries) +- [ ] XSS prevention (sanitized output) +- [ ] CSRF protection (if applicable) +- [ ] Secrets stored securely (not in code/logs) +- [ ] Rate limiting considered (if applicable) + +## ๐Ÿ“‹ Pre-Merge Checklist + + + +- [ ] All tests pass locally +- [ ] All pre-commit hooks pass +- [ ] Code has been self-reviewed +- [ ] Changes generate no new warnings +- [ ] Dependent changes have been merged +- [ ] Documentation has been updated +- [ ] Reviewer(s) have approved the PR +- [ ] Branch is up to date with base branch +- [ ] Commit messages are clean and descriptive +- [ ] Ready for production deployment + +## ๐Ÿ”— Additional Context + + + +## ๐Ÿšฆ Status + + + +- [ ] ๐Ÿ”ด Draft - Work in progress +- [ ] ๐ŸŸก Ready for Review - Code complete, needs review +- [ ] ๐ŸŸข Approved - Ready to merge +- [ ] ๐Ÿ”ต Merged - Deployed to staging +- [ ] โœ… Complete - Deployed to production + +--- + + diff --git a/src/agents/system-prompt.ts b/src/agents/system-prompt.ts index ed97fd539..9624fdb2d 100644 --- a/src/agents/system-prompt.ts +++ b/src/agents/system-prompt.ts @@ -83,21 +83,21 @@ function buildMessagingSection(params: { "- Never use exec/curl for provider messaging; Moltbot handles all routing internally.", params.availableTools.has("message") ? [ - "", - "### message tool", - "- Use `message` for proactive sends + channel actions (polls, reactions, etc.).", - "- For `action=send`, include `to` and `message`.", - `- If multiple channels are configured, pass \`channel\` (${params.messageChannelOptions}).`, - `- If you use \`message\` (\`action=send\`) to deliver your user-visible reply, respond with ONLY: ${SILENT_REPLY_TOKEN} (avoid duplicate replies).`, - params.inlineButtonsEnabled - ? "- Inline buttons supported. Use `action=send` with `buttons=[[{text,callback_data}]]` (callback_data routes back as a user message)." - : params.runtimeChannel - ? `- Inline buttons not enabled for ${params.runtimeChannel}. If you need them, ask to set ${params.runtimeChannel}.capabilities.inlineButtons ("dm"|"group"|"all"|"allowlist").` - : "", - ...(params.messageToolHints ?? []), - ] - .filter(Boolean) - .join("\n") + "", + "### message tool", + "- Use `message` for proactive sends + channel actions (polls, reactions, etc.).", + "- For `action=send`, include `to` and `message`.", + `- If multiple channels are configured, pass \`channel\` (${params.messageChannelOptions}).`, + `- If you use \`message\` (\`action=send\`) to deliver your user-visible reply, respond with ONLY: ${SILENT_REPLY_TOKEN} (avoid duplicate replies).`, + params.inlineButtonsEnabled + ? "- Inline buttons supported. Use `action=send` with `buttons=[[{text,callback_data}]]` (callback_data routes back as a user message)." + : params.runtimeChannel + ? `- Inline buttons not enabled for ${params.runtimeChannel}. If you need them, ask to set ${params.runtimeChannel}.capabilities.inlineButtons ("dm"|"group"|"all"|"allowlist").` + : "", + ...(params.messageToolHints ?? []), + ] + .filter(Boolean) + .join("\n") : "", "", ]; @@ -282,15 +282,15 @@ export function buildAgentSystemPrompt(params: { : undefined; const reasoningHint = params.reasoningTagHint ? [ - "ALL internal reasoning MUST be inside ....", - "Do not output any analysis outside .", - "Format every reply as ... then ..., with no other text.", - "Only the final user-visible reply may appear inside .", - "Only text inside is shown to the user; everything else is discarded and never seen by the user.", - "Example:", - "Short internal reasoning.", - "Hey there! What would you like to do next?", - ].join(" ") + "ALL internal reasoning MUST be inside ....", + "Do not output any analysis outside .", + "Format every reply as ... then ..., with no other text.", + "Only the final user-visible reply may appear inside .", + "Only text inside is shown to the user; everything else is discarded and never seen by the user.", + "Example:", + "Short internal reasoning.", + "Hey there! What would you like to do next?", + ].join(" ") : undefined; const reasoningLevel = params.reasoningLevel ?? "off"; const userTimezone = params.userTimezone?.trim(); @@ -336,21 +336,21 @@ export function buildAgentSystemPrompt(params: { toolLines.length > 0 ? toolLines.join("\n") : [ - "Pi lists the standard tools above. This runtime enables:", - "- grep: search file contents for patterns", - "- find: find files by glob pattern", - "- ls: list directory contents", - "- apply_patch: apply multi-file patches", - `- ${execToolName}: run shell commands (supports background via yieldMs/background)`, - `- ${processToolName}: manage background exec sessions`, - "- browser: control clawd's dedicated browser", - "- canvas: present/eval/snapshot the Canvas", - "- nodes: list/describe/notify/camera/screen on paired nodes", - "- cron: manage cron jobs and wake events (use for reminders; when scheduling a reminder, write the systemEvent text as something that will read like a reminder when it fires, and mention that it is a reminder depending on the time gap between setting and firing; include recent context in reminder text if appropriate)", - "- sessions_list: list sessions", - "- sessions_history: fetch session history", - "- sessions_send: send to another session", - ].join("\n"), + "Pi lists the standard tools above. This runtime enables:", + "- grep: search file contents for patterns", + "- find: find files by glob pattern", + "- ls: list directory contents", + "- apply_patch: apply multi-file patches", + `- ${execToolName}: run shell commands (supports background via yieldMs/background)`, + `- ${processToolName}: manage background exec sessions`, + "- browser: control clawd's dedicated browser", + "- canvas: present/eval/snapshot the Canvas", + "- nodes: list/describe/notify/camera/screen on paired nodes", + "- cron: manage cron jobs and wake events (use for reminders; when scheduling a reminder, write the systemEvent text as something that will read like a reminder when it fires, and mention that it is a reminder depending on the time gap between setting and firing; include recent context in reminder text if appropriate)", + "- sessions_list: list sessions", + "- sessions_history: fetch session history", + "- sessions_send: send to another session", + ].join("\n"), "TOOLS.md does not control tool availability; it is user guidance for how to use external tools.", "If a task is more complex or takes longer, spawn a sub-agent. It will do the work for you and ping you when it's done. You can always check up on it.", "", @@ -375,11 +375,11 @@ export function buildAgentSystemPrompt(params: { hasGateway && !isMinimal ? "## Moltbot Self-Update" : "", hasGateway && !isMinimal ? [ - "Get Updates (self-update) is ONLY allowed when the user explicitly asks for it.", - "Do not run config.apply or update.run unless the user explicitly requests an update or config change; if it's not explicit, ask first.", - "Actions: config.get, config.schema, config.apply (validate + write full config, then restart), update.run (update deps or git, then restart).", - "After restart, Moltbot pings the last active session automatically.", - ].join("\n") + "Get Updates (self-update) is ONLY allowed when the user explicitly asks for it.", + "Do not run config.apply or update.run unless the user explicitly requests an update or config change; if it's not explicit, ask first.", + "Actions: config.get, config.schema, config.apply (validate + write full config, then restart), update.run (update deps or git, then restart).", + "After restart, Moltbot pings the last active session automatically.", + ].join("\n") : "", hasGateway && !isMinimal ? "" : "", "", @@ -399,47 +399,57 @@ export function buildAgentSystemPrompt(params: { "Treat this directory as the single global workspace for file operations unless explicitly instructed otherwise.", ...workspaceNotes, "", + ...(runtimeInfo?.os?.toLowerCase().includes("windows") + ? [ + "## Windows Shell Guidance", + "You are running on Windows (PowerShell).", + "- Use PowerShell syntax (e.g. `$env:VAR` instead of `%VAR%` or `$VAR`).", + "- Do NOT use Unix commands like `grep`, `sed`, `awk`, `head`, `tail` unless you are sure they are installed.", + "- Use `findstr` or `Select-String` instead of `grep`.", + "- Use `Get-ChildItem` (dir/ls) with `-Recurse` instead of `find`.", + "", + ] + : []), ...docsSection, params.sandboxInfo?.enabled ? "## Sandbox" : "", params.sandboxInfo?.enabled ? [ - "You are running in a sandboxed runtime (tools execute in Docker).", - "Some tools may be unavailable due to sandbox policy.", - "Sub-agents stay sandboxed (no elevated/host access). Need outside-sandbox read/write? Don't spawn; ask first.", - params.sandboxInfo.workspaceDir - ? `Sandbox workspace: ${params.sandboxInfo.workspaceDir}` + "You are running in a sandboxed runtime (tools execute in Docker).", + "Some tools may be unavailable due to sandbox policy.", + "Sub-agents stay sandboxed (no elevated/host access). Need outside-sandbox read/write? Don't spawn; ask first.", + params.sandboxInfo.workspaceDir + ? `Sandbox workspace: ${params.sandboxInfo.workspaceDir}` + : "", + params.sandboxInfo.workspaceAccess + ? `Agent workspace access: ${params.sandboxInfo.workspaceAccess}${params.sandboxInfo.agentWorkspaceMount + ? ` (mounted at ${params.sandboxInfo.agentWorkspaceMount})` + : "" + }` + : "", + params.sandboxInfo.browserBridgeUrl ? "Sandbox browser: enabled." : "", + params.sandboxInfo.browserNoVncUrl + ? `Sandbox browser observer (noVNC): ${params.sandboxInfo.browserNoVncUrl}` + : "", + params.sandboxInfo.hostBrowserAllowed === true + ? "Host browser control: allowed." + : params.sandboxInfo.hostBrowserAllowed === false + ? "Host browser control: blocked." : "", - params.sandboxInfo.workspaceAccess - ? `Agent workspace access: ${params.sandboxInfo.workspaceAccess}${ - params.sandboxInfo.agentWorkspaceMount - ? ` (mounted at ${params.sandboxInfo.agentWorkspaceMount})` - : "" - }` - : "", - params.sandboxInfo.browserBridgeUrl ? "Sandbox browser: enabled." : "", - params.sandboxInfo.browserNoVncUrl - ? `Sandbox browser observer (noVNC): ${params.sandboxInfo.browserNoVncUrl}` - : "", - params.sandboxInfo.hostBrowserAllowed === true - ? "Host browser control: allowed." - : params.sandboxInfo.hostBrowserAllowed === false - ? "Host browser control: blocked." - : "", - params.sandboxInfo.elevated?.allowed - ? "Elevated exec is available for this session." - : "", - params.sandboxInfo.elevated?.allowed - ? "User can toggle with /elevated on|off|ask|full." - : "", - params.sandboxInfo.elevated?.allowed - ? "You may also send /elevated on|off|ask|full when needed." - : "", - params.sandboxInfo.elevated?.allowed - ? `Current elevated level: ${params.sandboxInfo.elevated.defaultLevel} (ask runs exec on host with approvals; full auto-approves).` - : "", - ] - .filter(Boolean) - .join("\n") + params.sandboxInfo.elevated?.allowed + ? "Elevated exec is available for this session." + : "", + params.sandboxInfo.elevated?.allowed + ? "User can toggle with /elevated on|off|ask|full." + : "", + params.sandboxInfo.elevated?.allowed + ? "You may also send /elevated on|off|ask|full when needed." + : "", + params.sandboxInfo.elevated?.allowed + ? `Current elevated level: ${params.sandboxInfo.elevated.defaultLevel} (ask runs exec on host with approvals; full auto-approves).` + : "", + ] + .filter(Boolean) + .join("\n") : "", params.sandboxInfo?.enabled ? "" : "", ...buildUserIdentitySection(ownerLine, isMinimal), @@ -472,22 +482,22 @@ export function buildAgentSystemPrompt(params: { const guidanceText = level === "minimal" ? [ - `Reactions are enabled for ${channel} in MINIMAL mode.`, - "React ONLY when truly relevant:", - "- Acknowledge important user requests or confirmations", - "- Express genuine sentiment (humor, appreciation) sparingly", - "- Avoid reacting to routine messages or your own replies", - "Guideline: at most 1 reaction per 5-10 exchanges.", - ].join("\n") + `Reactions are enabled for ${channel} in MINIMAL mode.`, + "React ONLY when truly relevant:", + "- Acknowledge important user requests or confirmations", + "- Express genuine sentiment (humor, appreciation) sparingly", + "- Avoid reacting to routine messages or your own replies", + "Guideline: at most 1 reaction per 5-10 exchanges.", + ].join("\n") : [ - `Reactions are enabled for ${channel} in EXTENSIVE mode.`, - "Feel free to react liberally:", - "- Acknowledge messages with appropriate emojis", - "- Express sentiment and personality through reactions", - "- React to interesting content, humor, or notable events", - "- Use reactions to confirm understanding or agreement", - "Guideline: react whenever it feels natural.", - ].join("\n"); + `Reactions are enabled for ${channel} in EXTENSIVE mode.`, + "Feel free to react liberally:", + "- Acknowledge messages with appropriate emojis", + "- Express sentiment and personality through reactions", + "- React to interesting content, humor, or notable events", + "- Use reactions to confirm understanding or agreement", + "Guideline: react whenever it feels natural.", + ].join("\n"); lines.push("## Reactions", guidanceText, ""); } if (reasoningHint) {