feat(system): add windows shell support and pr template

This commit is contained in:
Nathan Hangen 2026-01-28 18:53:30 -05:00
parent 109ac1c549
commit a91e626078
2 changed files with 420 additions and 95 deletions

315
.github/PULL_REQUEST_TEMPLATE.md vendored Normal file
View File

@ -0,0 +1,315 @@
# Pull Request: [Title]
<!--
Guidelines for a great PR:
- Use a clear, descriptive title following conventional commits format
- Fill out all relevant sections below
- Delete sections that don't apply (but keep the core sections)
- Reference related issues and PRs
- Add screenshots/videos for UI changes
- Ensure all tests pass and code is properly formatted
-->
## 📋 Summary
<!--
Provide a clear, concise summary (2-4 sentences) of what this PR does.
Focus on WHAT changed and WHY, not HOW (code explains the how).
-->
## 🎯 Related Issues
<!--
Link to related issues, PRs, or documentation:
- Closes #123
- Related to #456
- Depends on #789
- Reference: [Document Name](/path/to/doc.md)
-->
Closes #
## 🚀 What's New
<!--
Detail the changes made in this PR. Organize by feature/component.
Use subheadings (###) for major sections.
Include code snippets for complex changes.
-->
### 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
<!-- Check all that apply -->
- [ ] 🐛 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
<!--
Describe testing performed to validate changes.
Include both automated tests and manual 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
<!-- Describe manual testing steps performed -->
**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
<!--
Include screenshots or videos for UI changes.
Use before/after comparisons for visual changes.
Delete this section if not applicable.
-->
### Before
<!-- Screenshot/video of previous behavior -->
### After
<!-- Screenshot/video of new behavior -->
## 🚀 Deployment Strategy
<!--
Describe how this should be deployed.
Include rollout plan for risky changes.
-->
### Deployment Steps
1. Step 1
2. Step 2
3. Step 3
### Configuration Changes
<!-- List any environment variables, feature flags, or config changes needed -->
- [ ] 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
<!--
Describe how to quickly rollback if issues occur.
Critical for production deployments.
-->
**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
<!--
Estimate cost impact for cloud services, APIs, storage, etc.
Delete if not applicable.
-->
**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
<!--
Describe performance impact (positive or negative).
Include benchmarks for significant changes.
-->
**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
<!--
Pre-commit hooks should catch most issues automatically.
Confirm code quality checks passed.
-->
- [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
<!--
Ensure documentation is updated for changes.
Delete sections that don't apply.
-->
- [ ] 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
<!--
Address security implications of changes.
Required for security-sensitive changes.
-->
- [ ] 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
<!--
Final checklist before merging.
All items should be checked.
-->
- [ ] 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
<!--
Add any additional context, screenshots, benchmarks, or notes.
Links to external resources, design docs, API references, etc.
-->
## 🚦 Status
<!-- Update as PR progresses -->
- [ ] 🔴 Draft - Work in progress
- [ ] 🟡 Ready for Review - Code complete, needs review
- [ ] 🟢 Approved - Ready to merge
- [ ] 🔵 Merged - Deployed to staging
- [ ] ✅ Complete - Deployed to production
---
<!--
For Reviewers:
- Check code quality and adherence to project standards
- Verify tests cover new functionality
- Confirm documentation is updated
- Test changes locally if possible
- Ensure security considerations are addressed
- Validate deployment plan is safe
-->

View File

@ -83,21 +83,21 @@ function buildMessagingSection(params: {
"- Never use exec/curl for provider messaging; Moltbot handles all routing internally.", "- Never use exec/curl for provider messaging; Moltbot handles all routing internally.",
params.availableTools.has("message") params.availableTools.has("message")
? [ ? [
"", "",
"### message tool", "### message tool",
"- Use `message` for proactive sends + channel actions (polls, reactions, etc.).", "- Use `message` for proactive sends + channel actions (polls, reactions, etc.).",
"- For `action=send`, include `to` and `message`.", "- For `action=send`, include `to` and `message`.",
`- If multiple channels are configured, pass \`channel\` (${params.messageChannelOptions}).`, `- 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).`, `- If you use \`message\` (\`action=send\`) to deliver your user-visible reply, respond with ONLY: ${SILENT_REPLY_TOKEN} (avoid duplicate replies).`,
params.inlineButtonsEnabled params.inlineButtonsEnabled
? "- Inline buttons supported. Use `action=send` with `buttons=[[{text,callback_data}]]` (callback_data routes back as a user message)." ? "- Inline buttons supported. Use `action=send` with `buttons=[[{text,callback_data}]]` (callback_data routes back as a user message)."
: params.runtimeChannel : params.runtimeChannel
? `- Inline buttons not enabled for ${params.runtimeChannel}. If you need them, ask to set ${params.runtimeChannel}.capabilities.inlineButtons ("dm"|"group"|"all"|"allowlist").` ? `- Inline buttons not enabled for ${params.runtimeChannel}. If you need them, ask to set ${params.runtimeChannel}.capabilities.inlineButtons ("dm"|"group"|"all"|"allowlist").`
: "", : "",
...(params.messageToolHints ?? []), ...(params.messageToolHints ?? []),
] ]
.filter(Boolean) .filter(Boolean)
.join("\n") .join("\n")
: "", : "",
"", "",
]; ];
@ -282,15 +282,15 @@ export function buildAgentSystemPrompt(params: {
: undefined; : undefined;
const reasoningHint = params.reasoningTagHint const reasoningHint = params.reasoningTagHint
? [ ? [
"ALL internal reasoning MUST be inside <think>...</think>.", "ALL internal reasoning MUST be inside <think>...</think>.",
"Do not output any analysis outside <think>.", "Do not output any analysis outside <think>.",
"Format every reply as <think>...</think> then <final>...</final>, with no other text.", "Format every reply as <think>...</think> then <final>...</final>, with no other text.",
"Only the final user-visible reply may appear inside <final>.", "Only the final user-visible reply may appear inside <final>.",
"Only text inside <final> is shown to the user; everything else is discarded and never seen by the user.", "Only text inside <final> is shown to the user; everything else is discarded and never seen by the user.",
"Example:", "Example:",
"<think>Short internal reasoning.</think>", "<think>Short internal reasoning.</think>",
"<final>Hey there! What would you like to do next?</final>", "<final>Hey there! What would you like to do next?</final>",
].join(" ") ].join(" ")
: undefined; : undefined;
const reasoningLevel = params.reasoningLevel ?? "off"; const reasoningLevel = params.reasoningLevel ?? "off";
const userTimezone = params.userTimezone?.trim(); const userTimezone = params.userTimezone?.trim();
@ -336,21 +336,21 @@ export function buildAgentSystemPrompt(params: {
toolLines.length > 0 toolLines.length > 0
? toolLines.join("\n") ? toolLines.join("\n")
: [ : [
"Pi lists the standard tools above. This runtime enables:", "Pi lists the standard tools above. This runtime enables:",
"- grep: search file contents for patterns", "- grep: search file contents for patterns",
"- find: find files by glob pattern", "- find: find files by glob pattern",
"- ls: list directory contents", "- ls: list directory contents",
"- apply_patch: apply multi-file patches", "- apply_patch: apply multi-file patches",
`- ${execToolName}: run shell commands (supports background via yieldMs/background)`, `- ${execToolName}: run shell commands (supports background via yieldMs/background)`,
`- ${processToolName}: manage background exec sessions`, `- ${processToolName}: manage background exec sessions`,
"- browser: control clawd's dedicated browser", "- browser: control clawd's dedicated browser",
"- canvas: present/eval/snapshot the Canvas", "- canvas: present/eval/snapshot the Canvas",
"- nodes: list/describe/notify/camera/screen on paired nodes", "- 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)", "- 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_list: list sessions",
"- sessions_history: fetch session history", "- sessions_history: fetch session history",
"- sessions_send: send to another session", "- sessions_send: send to another session",
].join("\n"), ].join("\n"),
"TOOLS.md does not control tool availability; it is user guidance for how to use external tools.", "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.", "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 ? "## Moltbot Self-Update" : "",
hasGateway && !isMinimal hasGateway && !isMinimal
? [ ? [
"Get Updates (self-update) is ONLY allowed when the user explicitly asks for it.", "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.", "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).", "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.", "After restart, Moltbot pings the last active session automatically.",
].join("\n") ].join("\n")
: "", : "",
hasGateway && !isMinimal ? "" : "", 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.", "Treat this directory as the single global workspace for file operations unless explicitly instructed otherwise.",
...workspaceNotes, ...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, ...docsSection,
params.sandboxInfo?.enabled ? "## Sandbox" : "", params.sandboxInfo?.enabled ? "## Sandbox" : "",
params.sandboxInfo?.enabled params.sandboxInfo?.enabled
? [ ? [
"You are running in a sandboxed runtime (tools execute in Docker).", "You are running in a sandboxed runtime (tools execute in Docker).",
"Some tools may be unavailable due to sandbox policy.", "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.", "Sub-agents stay sandboxed (no elevated/host access). Need outside-sandbox read/write? Don't spawn; ask first.",
params.sandboxInfo.workspaceDir params.sandboxInfo.workspaceDir
? `Sandbox workspace: ${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 params.sandboxInfo.elevated?.allowed
? `Agent workspace access: ${params.sandboxInfo.workspaceAccess}${ ? "Elevated exec is available for this session."
params.sandboxInfo.agentWorkspaceMount : "",
? ` (mounted at ${params.sandboxInfo.agentWorkspaceMount})` params.sandboxInfo.elevated?.allowed
: "" ? "User can toggle with /elevated on|off|ask|full."
}` : "",
: "", params.sandboxInfo.elevated?.allowed
params.sandboxInfo.browserBridgeUrl ? "Sandbox browser: enabled." : "", ? "You may also send /elevated on|off|ask|full when needed."
params.sandboxInfo.browserNoVncUrl : "",
? `Sandbox browser observer (noVNC): ${params.sandboxInfo.browserNoVncUrl}` params.sandboxInfo.elevated?.allowed
: "", ? `Current elevated level: ${params.sandboxInfo.elevated.defaultLevel} (ask runs exec on host with approvals; full auto-approves).`
params.sandboxInfo.hostBrowserAllowed === true : "",
? "Host browser control: allowed." ]
: params.sandboxInfo.hostBrowserAllowed === false .filter(Boolean)
? "Host browser control: blocked." .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 ? "" : "", params.sandboxInfo?.enabled ? "" : "",
...buildUserIdentitySection(ownerLine, isMinimal), ...buildUserIdentitySection(ownerLine, isMinimal),
@ -472,22 +482,22 @@ export function buildAgentSystemPrompt(params: {
const guidanceText = const guidanceText =
level === "minimal" level === "minimal"
? [ ? [
`Reactions are enabled for ${channel} in MINIMAL mode.`, `Reactions are enabled for ${channel} in MINIMAL mode.`,
"React ONLY when truly relevant:", "React ONLY when truly relevant:",
"- Acknowledge important user requests or confirmations", "- Acknowledge important user requests or confirmations",
"- Express genuine sentiment (humor, appreciation) sparingly", "- Express genuine sentiment (humor, appreciation) sparingly",
"- Avoid reacting to routine messages or your own replies", "- Avoid reacting to routine messages or your own replies",
"Guideline: at most 1 reaction per 5-10 exchanges.", "Guideline: at most 1 reaction per 5-10 exchanges.",
].join("\n") ].join("\n")
: [ : [
`Reactions are enabled for ${channel} in EXTENSIVE mode.`, `Reactions are enabled for ${channel} in EXTENSIVE mode.`,
"Feel free to react liberally:", "Feel free to react liberally:",
"- Acknowledge messages with appropriate emojis", "- Acknowledge messages with appropriate emojis",
"- Express sentiment and personality through reactions", "- Express sentiment and personality through reactions",
"- React to interesting content, humor, or notable events", "- React to interesting content, humor, or notable events",
"- Use reactions to confirm understanding or agreement", "- Use reactions to confirm understanding or agreement",
"Guideline: react whenever it feels natural.", "Guideline: react whenever it feels natural.",
].join("\n"); ].join("\n");
lines.push("## Reactions", guidanceText, ""); lines.push("## Reactions", guidanceText, "");
} }
if (reasoningHint) { if (reasoningHint) {