Spaces:
Paused
Paused
Upload 4501 files
Browse filesThis view is limited to 50 files because it contains too many changes. See raw diff
- .agent/workflows/update_clawdbot.md +366 -0
- .detect-secrets.cfg +30 -0
- .dockerignore +48 -0
- .env.example +5 -0
- .gitattributes +21 -35
- .github/FUNDING.yml +1 -0
- .github/ISSUE_TEMPLATE/bug_report.md +28 -0
- .github/ISSUE_TEMPLATE/config.yml +8 -0
- .github/ISSUE_TEMPLATE/feature_request.md +18 -0
- .github/actionlint.yaml +17 -0
- .github/dependabot.yml +113 -0
- .github/labeler.yml +222 -0
- .github/workflows/auto-response.yml +65 -0
- .github/workflows/ci.yml +646 -0
- .github/workflows/docker-release.yml +143 -0
- .github/workflows/install-smoke.yml +41 -0
- .github/workflows/labeler.yml +24 -0
- .github/workflows/workflow-sanity.yml +37 -0
- .gitignore +73 -0
- .npmrc +1 -0
- .oxfmtrc.jsonc +5 -0
- .oxlintrc.json +12 -0
- .pre-commit-config.yaml +105 -0
- .prettierignore +1 -0
- .secrets.baseline +2191 -0
- .shellcheckrc +25 -0
- .swiftformat +51 -0
- .swiftlint.yml +148 -0
- AGENTS.md +163 -0
- CHANGELOG.md +0 -0
- CLAUDE.md +1 -0
- CONTRIBUTING.md +52 -0
- Dockerfile +40 -0
- Dockerfile.sandbox +16 -0
- Dockerfile.sandbox-browser +28 -0
- LICENSE +21 -0
- README-header.png +3 -0
- README.md +512 -12
- SECURITY.md +61 -0
- Swabble/.github/workflows/ci.yml +54 -0
- Swabble/.gitignore +33 -0
- Swabble/.swiftformat +8 -0
- Swabble/.swiftlint.yml +43 -0
- Swabble/CHANGELOG.md +11 -0
- Swabble/LICENSE +21 -0
- Swabble/Package.resolved +33 -0
- Swabble/Package.swift +55 -0
- Swabble/README.md +111 -0
- Swabble/Sources/SwabbleCore/Config/Config.swift +77 -0
- Swabble/Sources/SwabbleCore/Hooks/HookExecutor.swift +75 -0
.agent/workflows/update_clawdbot.md
ADDED
|
@@ -0,0 +1,366 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
description: Update Clawdbot from upstream when branch has diverged (ahead/behind)
|
| 3 |
+
---
|
| 4 |
+
|
| 5 |
+
# Clawdbot Upstream Sync Workflow
|
| 6 |
+
|
| 7 |
+
Use this workflow when your fork has diverged from upstream (e.g., "18 commits ahead, 29 commits behind").
|
| 8 |
+
|
| 9 |
+
## Quick Reference
|
| 10 |
+
|
| 11 |
+
```bash
|
| 12 |
+
# Check divergence status
|
| 13 |
+
git fetch upstream && git rev-list --left-right --count main...upstream/main
|
| 14 |
+
|
| 15 |
+
# Full sync (rebase preferred)
|
| 16 |
+
git fetch upstream && git rebase upstream/main && pnpm install && pnpm build && ./scripts/restart-mac.sh
|
| 17 |
+
|
| 18 |
+
# Check for Swift 6.2 issues after sync
|
| 19 |
+
grep -r "FileManager\.default\|Thread\.isMainThread" src/ apps/ --include="*.swift"
|
| 20 |
+
```
|
| 21 |
+
|
| 22 |
+
---
|
| 23 |
+
|
| 24 |
+
## Step 1: Assess Divergence
|
| 25 |
+
|
| 26 |
+
```bash
|
| 27 |
+
git fetch upstream
|
| 28 |
+
git log --oneline --left-right main...upstream/main | head -20
|
| 29 |
+
```
|
| 30 |
+
|
| 31 |
+
This shows:
|
| 32 |
+
- `<` = your local commits (ahead)
|
| 33 |
+
- `>` = upstream commits you're missing (behind)
|
| 34 |
+
|
| 35 |
+
**Decision point:**
|
| 36 |
+
- Few local commits, many upstream → **Rebase** (cleaner history)
|
| 37 |
+
- Many local commits or shared branch → **Merge** (preserves history)
|
| 38 |
+
|
| 39 |
+
---
|
| 40 |
+
|
| 41 |
+
## Step 2A: Rebase Strategy (Preferred)
|
| 42 |
+
|
| 43 |
+
Replays your commits on top of upstream. Results in linear history.
|
| 44 |
+
|
| 45 |
+
```bash
|
| 46 |
+
# Ensure working tree is clean
|
| 47 |
+
git status
|
| 48 |
+
|
| 49 |
+
# Rebase onto upstream
|
| 50 |
+
git rebase upstream/main
|
| 51 |
+
```
|
| 52 |
+
|
| 53 |
+
### Handling Rebase Conflicts
|
| 54 |
+
|
| 55 |
+
```bash
|
| 56 |
+
# When conflicts occur:
|
| 57 |
+
# 1. Fix conflicts in the listed files
|
| 58 |
+
# 2. Stage resolved files
|
| 59 |
+
git add <resolved-files>
|
| 60 |
+
|
| 61 |
+
# 3. Continue rebase
|
| 62 |
+
git rebase --continue
|
| 63 |
+
|
| 64 |
+
# If a commit is no longer needed (already in upstream):
|
| 65 |
+
git rebase --skip
|
| 66 |
+
|
| 67 |
+
# To abort and return to original state:
|
| 68 |
+
git rebase --abort
|
| 69 |
+
```
|
| 70 |
+
|
| 71 |
+
### Common Conflict Patterns
|
| 72 |
+
|
| 73 |
+
| File | Resolution |
|
| 74 |
+
|------|------------|
|
| 75 |
+
| `package.json` | Take upstream deps, keep local scripts if needed |
|
| 76 |
+
| `pnpm-lock.yaml` | Accept upstream, regenerate with `pnpm install` |
|
| 77 |
+
| `*.patch` files | Usually take upstream version |
|
| 78 |
+
| Source files | Merge logic carefully, prefer upstream structure |
|
| 79 |
+
|
| 80 |
+
---
|
| 81 |
+
|
| 82 |
+
## Step 2B: Merge Strategy (Alternative)
|
| 83 |
+
|
| 84 |
+
Preserves all history with a merge commit.
|
| 85 |
+
|
| 86 |
+
```bash
|
| 87 |
+
git merge upstream/main --no-edit
|
| 88 |
+
```
|
| 89 |
+
|
| 90 |
+
Resolve conflicts same as rebase, then:
|
| 91 |
+
```bash
|
| 92 |
+
git add <resolved-files>
|
| 93 |
+
git commit
|
| 94 |
+
```
|
| 95 |
+
|
| 96 |
+
---
|
| 97 |
+
|
| 98 |
+
## Step 3: Rebuild Everything
|
| 99 |
+
|
| 100 |
+
After sync completes:
|
| 101 |
+
|
| 102 |
+
```bash
|
| 103 |
+
# Install dependencies (regenerates lock if needed)
|
| 104 |
+
pnpm install
|
| 105 |
+
|
| 106 |
+
# Build TypeScript
|
| 107 |
+
pnpm build
|
| 108 |
+
|
| 109 |
+
# Build UI assets
|
| 110 |
+
pnpm ui:build
|
| 111 |
+
|
| 112 |
+
# Run diagnostics
|
| 113 |
+
pnpm clawdbot doctor
|
| 114 |
+
```
|
| 115 |
+
|
| 116 |
+
---
|
| 117 |
+
|
| 118 |
+
## Step 4: Rebuild macOS App
|
| 119 |
+
|
| 120 |
+
```bash
|
| 121 |
+
# Full rebuild, sign, and launch
|
| 122 |
+
./scripts/restart-mac.sh
|
| 123 |
+
|
| 124 |
+
# Or just package without restart
|
| 125 |
+
pnpm mac:package
|
| 126 |
+
```
|
| 127 |
+
|
| 128 |
+
### Install to /Applications
|
| 129 |
+
|
| 130 |
+
```bash
|
| 131 |
+
# Kill running app
|
| 132 |
+
pkill -x "Clawdbot" || true
|
| 133 |
+
|
| 134 |
+
# Move old version
|
| 135 |
+
mv /Applications/Clawdbot.app /tmp/Clawdbot-backup.app
|
| 136 |
+
|
| 137 |
+
# Install new build
|
| 138 |
+
cp -R dist/Clawdbot.app /Applications/
|
| 139 |
+
|
| 140 |
+
# Launch
|
| 141 |
+
open /Applications/Clawdbot.app
|
| 142 |
+
```
|
| 143 |
+
|
| 144 |
+
---
|
| 145 |
+
|
| 146 |
+
## Step 4A: Verify macOS App & Agent
|
| 147 |
+
|
| 148 |
+
After rebuilding the macOS app, always verify it works correctly:
|
| 149 |
+
|
| 150 |
+
```bash
|
| 151 |
+
# Check gateway health
|
| 152 |
+
pnpm clawdbot health
|
| 153 |
+
|
| 154 |
+
# Verify no zombie processes
|
| 155 |
+
ps aux | grep -E "(clawdbot|gateway)" | grep -v grep
|
| 156 |
+
|
| 157 |
+
# Test agent functionality by sending a verification message
|
| 158 |
+
pnpm clawdbot agent --message "Verification: macOS app rebuild successful - agent is responding." --session-id YOUR_TELEGRAM_SESSION_ID
|
| 159 |
+
|
| 160 |
+
# Confirm the message was received on Telegram
|
| 161 |
+
# (Check your Telegram chat with the bot)
|
| 162 |
+
```
|
| 163 |
+
|
| 164 |
+
**Important:** Always wait for the Telegram verification message before proceeding. If the agent doesn't respond, troubleshoot the gateway or model configuration before pushing.
|
| 165 |
+
|
| 166 |
+
---
|
| 167 |
+
|
| 168 |
+
## Step 5: Handle Swift/macOS Build Issues (Common After Upstream Sync)
|
| 169 |
+
|
| 170 |
+
Upstream updates may introduce Swift 6.2 / macOS 26 SDK incompatibilities. Use analyze-mode for systematic debugging:
|
| 171 |
+
|
| 172 |
+
### Analyze-Mode Investigation
|
| 173 |
+
```bash
|
| 174 |
+
# Gather context with parallel agents
|
| 175 |
+
morph-mcp_warpgrep_codebase_search search_string="Find deprecated FileManager.default and Thread.isMainThread usages in Swift files" repo_path="/Volumes/Main SSD/Developer/clawdis"
|
| 176 |
+
morph-mcp_warpgrep_codebase_search search_string="Locate Peekaboo submodule and macOS app Swift files with concurrency issues" repo_path="/Volumes/Main SSD/Developer/clawdis"
|
| 177 |
+
```
|
| 178 |
+
|
| 179 |
+
### Common Swift 6.2 Fixes
|
| 180 |
+
|
| 181 |
+
**FileManager.default Deprecation:**
|
| 182 |
+
```bash
|
| 183 |
+
# Search for deprecated usage
|
| 184 |
+
grep -r "FileManager\.default" src/ apps/ --include="*.swift"
|
| 185 |
+
|
| 186 |
+
# Replace with proper initialization
|
| 187 |
+
# OLD: FileManager.default
|
| 188 |
+
# NEW: FileManager()
|
| 189 |
+
```
|
| 190 |
+
|
| 191 |
+
**Thread.isMainThread Deprecation:**
|
| 192 |
+
```bash
|
| 193 |
+
# Search for deprecated usage
|
| 194 |
+
grep -r "Thread\.isMainThread" src/ apps/ --include="*.swift"
|
| 195 |
+
|
| 196 |
+
# Replace with modern concurrency check
|
| 197 |
+
# OLD: Thread.isMainThread
|
| 198 |
+
# NEW: await MainActor.run { ... } or DispatchQueue.main.sync { ... }
|
| 199 |
+
```
|
| 200 |
+
|
| 201 |
+
### Peekaboo Submodule Fixes
|
| 202 |
+
```bash
|
| 203 |
+
# Check Peekaboo for concurrency issues
|
| 204 |
+
cd src/canvas-host/a2ui
|
| 205 |
+
grep -r "Thread\.isMainThread\|FileManager\.default" . --include="*.swift"
|
| 206 |
+
|
| 207 |
+
# Fix and rebuild submodule
|
| 208 |
+
cd /Volumes/Main SSD/Developer/clawdis
|
| 209 |
+
pnpm canvas:a2ui:bundle
|
| 210 |
+
```
|
| 211 |
+
|
| 212 |
+
### macOS App Concurrency Fixes
|
| 213 |
+
```bash
|
| 214 |
+
# Check macOS app for issues
|
| 215 |
+
grep -r "Thread\.isMainThread\|FileManager\.default" apps/macos/ --include="*.swift"
|
| 216 |
+
|
| 217 |
+
# Clean and rebuild after fixes
|
| 218 |
+
cd apps/macos && rm -rf .build .swiftpm
|
| 219 |
+
./scripts/restart-mac.sh
|
| 220 |
+
```
|
| 221 |
+
|
| 222 |
+
### Model Configuration Updates
|
| 223 |
+
If upstream introduced new model configurations:
|
| 224 |
+
```bash
|
| 225 |
+
# Check for OpenRouter API key requirements
|
| 226 |
+
grep -r "openrouter\|OPENROUTER" src/ --include="*.ts" --include="*.js"
|
| 227 |
+
|
| 228 |
+
# Update clawdbot.json with fallback chains
|
| 229 |
+
# Add model fallback configurations as needed
|
| 230 |
+
```
|
| 231 |
+
|
| 232 |
+
---
|
| 233 |
+
|
| 234 |
+
## Step 6: Verify & Push
|
| 235 |
+
|
| 236 |
+
```bash
|
| 237 |
+
# Verify everything works
|
| 238 |
+
pnpm clawdbot health
|
| 239 |
+
pnpm test
|
| 240 |
+
|
| 241 |
+
# Push (force required after rebase)
|
| 242 |
+
git push origin main --force-with-lease
|
| 243 |
+
|
| 244 |
+
# Or regular push after merge
|
| 245 |
+
git push origin main
|
| 246 |
+
```
|
| 247 |
+
|
| 248 |
+
---
|
| 249 |
+
|
| 250 |
+
## Troubleshooting
|
| 251 |
+
|
| 252 |
+
### Build Fails After Sync
|
| 253 |
+
|
| 254 |
+
```bash
|
| 255 |
+
# Clean and rebuild
|
| 256 |
+
rm -rf node_modules dist
|
| 257 |
+
pnpm install
|
| 258 |
+
pnpm build
|
| 259 |
+
```
|
| 260 |
+
|
| 261 |
+
### Type Errors (Bun/Node Incompatibility)
|
| 262 |
+
|
| 263 |
+
Common issue: `fetch.preconnect` type mismatch. Fix by using `FetchLike` type instead of `typeof fetch`.
|
| 264 |
+
|
| 265 |
+
### macOS App Crashes on Launch
|
| 266 |
+
|
| 267 |
+
Usually resource bundle mismatch. Full rebuild required:
|
| 268 |
+
```bash
|
| 269 |
+
cd apps/macos && rm -rf .build .swiftpm
|
| 270 |
+
./scripts/restart-mac.sh
|
| 271 |
+
```
|
| 272 |
+
|
| 273 |
+
### Patch Failures
|
| 274 |
+
|
| 275 |
+
```bash
|
| 276 |
+
# Check patch status
|
| 277 |
+
pnpm install 2>&1 | grep -i patch
|
| 278 |
+
|
| 279 |
+
# If patches fail, they may need updating for new dep versions
|
| 280 |
+
# Check patches/ directory against package.json patchedDependencies
|
| 281 |
+
```
|
| 282 |
+
|
| 283 |
+
### Swift 6.2 / macOS 26 SDK Build Failures
|
| 284 |
+
|
| 285 |
+
**Symptoms:** Build fails with deprecation warnings about `FileManager.default` or `Thread.isMainThread`
|
| 286 |
+
|
| 287 |
+
**Search-Mode Investigation:**
|
| 288 |
+
```bash
|
| 289 |
+
# Exhaustive search for deprecated APIs
|
| 290 |
+
morph-mcp_warpgrep_codebase_search search_string="Find all Swift files using deprecated FileManager.default or Thread.isMainThread" repo_path="/Volumes/Main SSD/Developer/clawdis"
|
| 291 |
+
```
|
| 292 |
+
|
| 293 |
+
**Quick Fix Commands:**
|
| 294 |
+
```bash
|
| 295 |
+
# Find all affected files
|
| 296 |
+
find . -name "*.swift" -exec grep -l "FileManager\.default\|Thread\.isMainThread" {} \;
|
| 297 |
+
|
| 298 |
+
# Replace FileManager.default with FileManager()
|
| 299 |
+
find . -name "*.swift" -exec sed -i '' 's/FileManager\.default/FileManager()/g' {} \;
|
| 300 |
+
|
| 301 |
+
# For Thread.isMainThread, need manual review of each usage
|
| 302 |
+
grep -rn "Thread\.isMainThread" --include="*.swift" .
|
| 303 |
+
```
|
| 304 |
+
|
| 305 |
+
**Rebuild After Fixes:**
|
| 306 |
+
```bash
|
| 307 |
+
# Clean all build artifacts
|
| 308 |
+
rm -rf apps/macos/.build apps/macos/.swiftpm
|
| 309 |
+
rm -rf src/canvas-host/a2ui/.build
|
| 310 |
+
|
| 311 |
+
# Rebuild Peekaboo bundle
|
| 312 |
+
pnpm canvas:a2ui:bundle
|
| 313 |
+
|
| 314 |
+
# Full macOS rebuild
|
| 315 |
+
./scripts/restart-mac.sh
|
| 316 |
+
```
|
| 317 |
+
|
| 318 |
+
---
|
| 319 |
+
|
| 320 |
+
## Automation Script
|
| 321 |
+
|
| 322 |
+
Save as `scripts/sync-upstream.sh`:
|
| 323 |
+
|
| 324 |
+
```bash
|
| 325 |
+
#!/usr/bin/env bash
|
| 326 |
+
set -euo pipefail
|
| 327 |
+
|
| 328 |
+
echo "==> Fetching upstream..."
|
| 329 |
+
git fetch upstream
|
| 330 |
+
|
| 331 |
+
echo "==> Current divergence:"
|
| 332 |
+
git rev-list --left-right --count main...upstream/main
|
| 333 |
+
|
| 334 |
+
echo "==> Rebasing onto upstream/main..."
|
| 335 |
+
git rebase upstream/main
|
| 336 |
+
|
| 337 |
+
echo "==> Installing dependencies..."
|
| 338 |
+
pnpm install
|
| 339 |
+
|
| 340 |
+
echo "==> Building..."
|
| 341 |
+
pnpm build
|
| 342 |
+
pnpm ui:build
|
| 343 |
+
|
| 344 |
+
echo "==> Running doctor..."
|
| 345 |
+
pnpm clawdbot doctor
|
| 346 |
+
|
| 347 |
+
echo "==> Rebuilding macOS app..."
|
| 348 |
+
./scripts/restart-mac.sh
|
| 349 |
+
|
| 350 |
+
echo "==> Verifying gateway health..."
|
| 351 |
+
pnpm clawdbot health
|
| 352 |
+
|
| 353 |
+
echo "==> Checking for Swift 6.2 compatibility issues..."
|
| 354 |
+
if grep -r "FileManager\.default\|Thread\.isMainThread" src/ apps/ --include="*.swift" --quiet; then
|
| 355 |
+
echo "⚠️ Found potential Swift 6.2 deprecated API usage"
|
| 356 |
+
echo " Run manual fixes or use analyze-mode investigation"
|
| 357 |
+
else
|
| 358 |
+
echo "✅ No obvious Swift deprecation issues found"
|
| 359 |
+
fi
|
| 360 |
+
|
| 361 |
+
echo "==> Testing agent functionality..."
|
| 362 |
+
# Note: Update YOUR_TELEGRAM_SESSION_ID with actual session ID
|
| 363 |
+
pnpm clawdbot agent --message "Verification: Upstream sync and macOS rebuild completed successfully." --session-id YOUR_TELEGRAM_SESSION_ID || echo "Warning: Agent test failed - check Telegram for verification message"
|
| 364 |
+
|
| 365 |
+
echo "==> Done! Check Telegram for verification message, then run 'git push --force-with-lease' when ready."
|
| 366 |
+
```
|
.detect-secrets.cfg
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# detect-secrets exclusion patterns (regex)
|
| 2 |
+
#
|
| 3 |
+
# Note: detect-secrets does not read this file by default. If you want these
|
| 4 |
+
# applied, wire them into your scan command (e.g. translate to --exclude-files
|
| 5 |
+
# / --exclude-lines) or into a baseline's filters_used.
|
| 6 |
+
|
| 7 |
+
[exclude-files]
|
| 8 |
+
# pnpm lockfiles contain lots of high-entropy package integrity blobs.
|
| 9 |
+
pattern = (^|/)pnpm-lock\.yaml$
|
| 10 |
+
# Generated output and vendored assets.
|
| 11 |
+
pattern = (^|/)(dist|vendor)/
|
| 12 |
+
# Local config file with allowlist patterns.
|
| 13 |
+
pattern = (^|/)\.detect-secrets\.cfg$
|
| 14 |
+
|
| 15 |
+
[exclude-lines]
|
| 16 |
+
# Fastlane checks for private key marker; not a real key.
|
| 17 |
+
pattern = key_content\.include\?\("BEGIN PRIVATE KEY"\)
|
| 18 |
+
# UI label string for Anthropic auth mode.
|
| 19 |
+
pattern = case \.apiKeyEnv: "API key \(env var\)"
|
| 20 |
+
# CodingKeys mapping uses apiKey literal.
|
| 21 |
+
pattern = case apikey = "apiKey"
|
| 22 |
+
# Schema labels referencing password fields (not actual secrets).
|
| 23 |
+
pattern = "gateway\.remote\.password"
|
| 24 |
+
pattern = "gateway\.auth\.password"
|
| 25 |
+
# Schema label for talk API key (label text only).
|
| 26 |
+
pattern = "talk\.apiKey"
|
| 27 |
+
# checking for typeof is not something we care about.
|
| 28 |
+
pattern = === "string"
|
| 29 |
+
# specific optional-chaining password check that didn't match the line above.
|
| 30 |
+
pattern = typeof remote\?\.password === "string"
|
.dockerignore
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
.git
|
| 2 |
+
.worktrees
|
| 3 |
+
.bun-cache
|
| 4 |
+
.bun
|
| 5 |
+
.tmp
|
| 6 |
+
**/.tmp
|
| 7 |
+
.DS_Store
|
| 8 |
+
**/.DS_Store
|
| 9 |
+
*.png
|
| 10 |
+
*.jpg
|
| 11 |
+
*.jpeg
|
| 12 |
+
*.webp
|
| 13 |
+
*.gif
|
| 14 |
+
*.mp4
|
| 15 |
+
*.mov
|
| 16 |
+
*.wav
|
| 17 |
+
*.mp3
|
| 18 |
+
node_modules
|
| 19 |
+
**/node_modules
|
| 20 |
+
.pnpm-store
|
| 21 |
+
**/.pnpm-store
|
| 22 |
+
.turbo
|
| 23 |
+
**/.turbo
|
| 24 |
+
.cache
|
| 25 |
+
**/.cache
|
| 26 |
+
.next
|
| 27 |
+
**/.next
|
| 28 |
+
coverage
|
| 29 |
+
**/coverage
|
| 30 |
+
*.log
|
| 31 |
+
tmp
|
| 32 |
+
**/tmp
|
| 33 |
+
|
| 34 |
+
# build artifacts
|
| 35 |
+
dist
|
| 36 |
+
**/dist
|
| 37 |
+
apps/macos/.build
|
| 38 |
+
apps/ios/build
|
| 39 |
+
**/*.trace
|
| 40 |
+
|
| 41 |
+
# large app trees not needed for CLI build
|
| 42 |
+
apps/
|
| 43 |
+
assets/
|
| 44 |
+
Peekaboo/
|
| 45 |
+
Swabble/
|
| 46 |
+
Core/
|
| 47 |
+
Users/
|
| 48 |
+
vendor/
|
.env.example
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copy to .env and fill with your Twilio credentials
|
| 2 |
+
TWILIO_ACCOUNT_SID=ACxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
| 3 |
+
TWILIO_AUTH_TOKEN=your_auth_token_here
|
| 4 |
+
# Must be a WhatsApp-enabled Twilio number, prefixed with whatsapp:
|
| 5 |
+
TWILIO_WHATSAPP_FROM=whatsapp:+17343367101
|
.gitattributes
CHANGED
|
@@ -1,35 +1,21 @@
|
|
| 1 |
-
*
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
*.pt filter=lfs diff=lfs merge=lfs -text
|
| 23 |
-
*.pth filter=lfs diff=lfs merge=lfs -text
|
| 24 |
-
*.rar filter=lfs diff=lfs merge=lfs -text
|
| 25 |
-
*.safetensors filter=lfs diff=lfs merge=lfs -text
|
| 26 |
-
saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
| 27 |
-
*.tar.* filter=lfs diff=lfs merge=lfs -text
|
| 28 |
-
*.tar filter=lfs diff=lfs merge=lfs -text
|
| 29 |
-
*.tflite filter=lfs diff=lfs merge=lfs -text
|
| 30 |
-
*.tgz filter=lfs diff=lfs merge=lfs -text
|
| 31 |
-
*.wasm filter=lfs diff=lfs merge=lfs -text
|
| 32 |
-
*.xz filter=lfs diff=lfs merge=lfs -text
|
| 33 |
-
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 34 |
-
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 35 |
-
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
|
|
|
| 1 |
+
* text=auto eol=lf
|
| 2 |
+
apps/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png filter=lfs diff=lfs merge=lfs -text
|
| 3 |
+
apps/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png filter=lfs diff=lfs merge=lfs -text
|
| 4 |
+
apps/ios/Sources/Assets.xcassets/AppIcon.appiconset/icon-1024.png filter=lfs diff=lfs merge=lfs -text
|
| 5 |
+
apps/macos/Icon.icon/Assets/clawdbot-mac.png filter=lfs diff=lfs merge=lfs -text
|
| 6 |
+
apps/macos/Sources/Clawdbot/Resources/Clawdbot.icns filter=lfs diff=lfs merge=lfs -text
|
| 7 |
+
assets/dmg-background-small.png filter=lfs diff=lfs merge=lfs -text
|
| 8 |
+
assets/dmg-background.png filter=lfs diff=lfs merge=lfs -text
|
| 9 |
+
docs/assets/showcase/agents-ui.jpg filter=lfs diff=lfs merge=lfs -text
|
| 10 |
+
docs/assets/showcase/bambu-cli.png filter=lfs diff=lfs merge=lfs -text
|
| 11 |
+
docs/assets/showcase/codexmonitor.png filter=lfs diff=lfs merge=lfs -text
|
| 12 |
+
docs/assets/showcase/gohome-grafana.png filter=lfs diff=lfs merge=lfs -text
|
| 13 |
+
docs/assets/showcase/ios-testflight.jpg filter=lfs diff=lfs merge=lfs -text
|
| 14 |
+
docs/assets/showcase/oura-health.png filter=lfs diff=lfs merge=lfs -text
|
| 15 |
+
docs/assets/showcase/pr-review-telegram.jpg filter=lfs diff=lfs merge=lfs -text
|
| 16 |
+
docs/assets/showcase/roof-camera-sky.jpg filter=lfs diff=lfs merge=lfs -text
|
| 17 |
+
docs/assets/showcase/snag.png filter=lfs diff=lfs merge=lfs -text
|
| 18 |
+
docs/assets/showcase/wienerlinien.png filter=lfs diff=lfs merge=lfs -text
|
| 19 |
+
docs/assets/showcase/winix-air-purifier.jpg filter=lfs diff=lfs merge=lfs -text
|
| 20 |
+
docs/images/mobile-ui-screenshot.png filter=lfs diff=lfs merge=lfs -text
|
| 21 |
+
README-header.png filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.github/FUNDING.yml
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
custom: ['https://github.com/sponsors/steipete']
|
.github/ISSUE_TEMPLATE/bug_report.md
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
name: Bug report
|
| 3 |
+
about: Report a problem or unexpected behavior in Clawdbot.
|
| 4 |
+
title: "[Bug]: "
|
| 5 |
+
labels: bug
|
| 6 |
+
---
|
| 7 |
+
|
| 8 |
+
## Summary
|
| 9 |
+
What went wrong?
|
| 10 |
+
|
| 11 |
+
## Steps to reproduce
|
| 12 |
+
1.
|
| 13 |
+
2.
|
| 14 |
+
3.
|
| 15 |
+
|
| 16 |
+
## Expected behavior
|
| 17 |
+
What did you expect to happen?
|
| 18 |
+
|
| 19 |
+
## Actual behavior
|
| 20 |
+
What actually happened?
|
| 21 |
+
|
| 22 |
+
## Environment
|
| 23 |
+
- Clawdbot version:
|
| 24 |
+
- OS:
|
| 25 |
+
- Install method (pnpm/npx/docker/etc):
|
| 26 |
+
|
| 27 |
+
## Logs or screenshots
|
| 28 |
+
Paste relevant logs or add screenshots (redact secrets).
|
.github/ISSUE_TEMPLATE/config.yml
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
blank_issues_enabled: true
|
| 2 |
+
contact_links:
|
| 3 |
+
- name: Onboarding
|
| 4 |
+
url: https://discord.gg/clawd
|
| 5 |
+
about: New to Clawdbot? Join Discord for setup guidance from Krill in #help.
|
| 6 |
+
- name: Support
|
| 7 |
+
url: https://discord.gg/clawd
|
| 8 |
+
about: Get help from Krill and the community on Discord in #help.
|
.github/ISSUE_TEMPLATE/feature_request.md
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
name: Feature request
|
| 3 |
+
about: Suggest an idea or improvement for Clawdbot.
|
| 4 |
+
title: "[Feature]: "
|
| 5 |
+
labels: enhancement
|
| 6 |
+
---
|
| 7 |
+
|
| 8 |
+
## Summary
|
| 9 |
+
Describe the problem you are trying to solve or the opportunity you see.
|
| 10 |
+
|
| 11 |
+
## Proposed solution
|
| 12 |
+
What would you like Clawdbot to do?
|
| 13 |
+
|
| 14 |
+
## Alternatives considered
|
| 15 |
+
Any other approaches you have considered?
|
| 16 |
+
|
| 17 |
+
## Additional context
|
| 18 |
+
Links, screenshots, or related issues.
|
.github/actionlint.yaml
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# actionlint configuration
|
| 2 |
+
# https://github.com/rhysd/actionlint/blob/main/docs/config.md
|
| 3 |
+
|
| 4 |
+
self-hosted-runner:
|
| 5 |
+
labels:
|
| 6 |
+
# Blacksmith CI runners
|
| 7 |
+
- blacksmith-4vcpu-ubuntu-2404
|
| 8 |
+
- blacksmith-4vcpu-windows-2025
|
| 9 |
+
|
| 10 |
+
# Ignore patterns for known issues
|
| 11 |
+
paths:
|
| 12 |
+
.github/workflows/**/*.yml:
|
| 13 |
+
ignore:
|
| 14 |
+
# Ignore shellcheck warnings (we run shellcheck separately)
|
| 15 |
+
- 'shellcheck reported issue.+'
|
| 16 |
+
# Ignore intentional if: false for disabled jobs
|
| 17 |
+
- 'constant expression "false" in condition'
|
.github/dependabot.yml
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Dependabot configuration
|
| 2 |
+
# https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file
|
| 3 |
+
|
| 4 |
+
version: 2
|
| 5 |
+
|
| 6 |
+
registries:
|
| 7 |
+
npm-npmjs:
|
| 8 |
+
type: npm-registry
|
| 9 |
+
url: https://registry.npmjs.org
|
| 10 |
+
replaces-base: true
|
| 11 |
+
|
| 12 |
+
updates:
|
| 13 |
+
# npm dependencies (root)
|
| 14 |
+
- package-ecosystem: npm
|
| 15 |
+
directory: /
|
| 16 |
+
schedule:
|
| 17 |
+
interval: weekly
|
| 18 |
+
cooldown:
|
| 19 |
+
default-days: 7
|
| 20 |
+
groups:
|
| 21 |
+
production:
|
| 22 |
+
dependency-type: production
|
| 23 |
+
update-types:
|
| 24 |
+
- minor
|
| 25 |
+
- patch
|
| 26 |
+
development:
|
| 27 |
+
dependency-type: development
|
| 28 |
+
update-types:
|
| 29 |
+
- minor
|
| 30 |
+
- patch
|
| 31 |
+
open-pull-requests-limit: 10
|
| 32 |
+
registries:
|
| 33 |
+
- npm-npmjs
|
| 34 |
+
|
| 35 |
+
# GitHub Actions
|
| 36 |
+
- package-ecosystem: github-actions
|
| 37 |
+
directory: /
|
| 38 |
+
schedule:
|
| 39 |
+
interval: weekly
|
| 40 |
+
cooldown:
|
| 41 |
+
default-days: 7
|
| 42 |
+
groups:
|
| 43 |
+
actions:
|
| 44 |
+
patterns:
|
| 45 |
+
- "*"
|
| 46 |
+
update-types:
|
| 47 |
+
- minor
|
| 48 |
+
- patch
|
| 49 |
+
open-pull-requests-limit: 5
|
| 50 |
+
|
| 51 |
+
# Swift Package Manager - macOS app
|
| 52 |
+
- package-ecosystem: swift
|
| 53 |
+
directory: /apps/macos
|
| 54 |
+
schedule:
|
| 55 |
+
interval: weekly
|
| 56 |
+
cooldown:
|
| 57 |
+
default-days: 7
|
| 58 |
+
groups:
|
| 59 |
+
swift-deps:
|
| 60 |
+
patterns:
|
| 61 |
+
- "*"
|
| 62 |
+
update-types:
|
| 63 |
+
- minor
|
| 64 |
+
- patch
|
| 65 |
+
open-pull-requests-limit: 5
|
| 66 |
+
|
| 67 |
+
# Swift Package Manager - shared ClawdbotKit
|
| 68 |
+
- package-ecosystem: swift
|
| 69 |
+
directory: /apps/shared/ClawdbotKit
|
| 70 |
+
schedule:
|
| 71 |
+
interval: weekly
|
| 72 |
+
cooldown:
|
| 73 |
+
default-days: 7
|
| 74 |
+
groups:
|
| 75 |
+
swift-deps:
|
| 76 |
+
patterns:
|
| 77 |
+
- "*"
|
| 78 |
+
update-types:
|
| 79 |
+
- minor
|
| 80 |
+
- patch
|
| 81 |
+
open-pull-requests-limit: 5
|
| 82 |
+
|
| 83 |
+
# Swift Package Manager - Swabble
|
| 84 |
+
- package-ecosystem: swift
|
| 85 |
+
directory: /Swabble
|
| 86 |
+
schedule:
|
| 87 |
+
interval: weekly
|
| 88 |
+
cooldown:
|
| 89 |
+
default-days: 7
|
| 90 |
+
groups:
|
| 91 |
+
swift-deps:
|
| 92 |
+
patterns:
|
| 93 |
+
- "*"
|
| 94 |
+
update-types:
|
| 95 |
+
- minor
|
| 96 |
+
- patch
|
| 97 |
+
open-pull-requests-limit: 5
|
| 98 |
+
|
| 99 |
+
# Gradle - Android app
|
| 100 |
+
- package-ecosystem: gradle
|
| 101 |
+
directory: /apps/android
|
| 102 |
+
schedule:
|
| 103 |
+
interval: weekly
|
| 104 |
+
cooldown:
|
| 105 |
+
default-days: 7
|
| 106 |
+
groups:
|
| 107 |
+
android-deps:
|
| 108 |
+
patterns:
|
| 109 |
+
- "*"
|
| 110 |
+
update-types:
|
| 111 |
+
- minor
|
| 112 |
+
- patch
|
| 113 |
+
open-pull-requests-limit: 5
|
.github/labeler.yml
ADDED
|
@@ -0,0 +1,222 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"channel: bluebubbles":
|
| 2 |
+
- changed-files:
|
| 3 |
+
- any-glob-to-any-file:
|
| 4 |
+
- "extensions/bluebubbles/**"
|
| 5 |
+
- "docs/channels/bluebubbles.md"
|
| 6 |
+
"channel: discord":
|
| 7 |
+
- changed-files:
|
| 8 |
+
- any-glob-to-any-file:
|
| 9 |
+
- "src/discord/**"
|
| 10 |
+
- "extensions/discord/**"
|
| 11 |
+
- "docs/channels/discord.md"
|
| 12 |
+
"channel: googlechat":
|
| 13 |
+
- changed-files:
|
| 14 |
+
- any-glob-to-any-file:
|
| 15 |
+
- "extensions/googlechat/**"
|
| 16 |
+
- "docs/channels/googlechat.md"
|
| 17 |
+
"channel: imessage":
|
| 18 |
+
- changed-files:
|
| 19 |
+
- any-glob-to-any-file:
|
| 20 |
+
- "src/imessage/**"
|
| 21 |
+
- "extensions/imessage/**"
|
| 22 |
+
- "docs/channels/imessage.md"
|
| 23 |
+
"channel: line":
|
| 24 |
+
- changed-files:
|
| 25 |
+
- any-glob-to-any-file:
|
| 26 |
+
- "extensions/line/**"
|
| 27 |
+
- "docs/channels/line.md"
|
| 28 |
+
"channel: matrix":
|
| 29 |
+
- changed-files:
|
| 30 |
+
- any-glob-to-any-file:
|
| 31 |
+
- "extensions/matrix/**"
|
| 32 |
+
- "docs/channels/matrix.md"
|
| 33 |
+
"channel: mattermost":
|
| 34 |
+
- changed-files:
|
| 35 |
+
- any-glob-to-any-file:
|
| 36 |
+
- "extensions/mattermost/**"
|
| 37 |
+
- "docs/channels/mattermost.md"
|
| 38 |
+
"channel: msteams":
|
| 39 |
+
- changed-files:
|
| 40 |
+
- any-glob-to-any-file:
|
| 41 |
+
- "extensions/msteams/**"
|
| 42 |
+
- "docs/channels/msteams.md"
|
| 43 |
+
"channel: nextcloud-talk":
|
| 44 |
+
- changed-files:
|
| 45 |
+
- any-glob-to-any-file:
|
| 46 |
+
- "extensions/nextcloud-talk/**"
|
| 47 |
+
- "docs/channels/nextcloud-talk.md"
|
| 48 |
+
"channel: nostr":
|
| 49 |
+
- changed-files:
|
| 50 |
+
- any-glob-to-any-file:
|
| 51 |
+
- "extensions/nostr/**"
|
| 52 |
+
- "docs/channels/nostr.md"
|
| 53 |
+
"channel: signal":
|
| 54 |
+
- changed-files:
|
| 55 |
+
- any-glob-to-any-file:
|
| 56 |
+
- "src/signal/**"
|
| 57 |
+
- "extensions/signal/**"
|
| 58 |
+
- "docs/channels/signal.md"
|
| 59 |
+
"channel: slack":
|
| 60 |
+
- changed-files:
|
| 61 |
+
- any-glob-to-any-file:
|
| 62 |
+
- "src/slack/**"
|
| 63 |
+
- "extensions/slack/**"
|
| 64 |
+
- "docs/channels/slack.md"
|
| 65 |
+
"channel: telegram":
|
| 66 |
+
- changed-files:
|
| 67 |
+
- any-glob-to-any-file:
|
| 68 |
+
- "src/telegram/**"
|
| 69 |
+
- "extensions/telegram/**"
|
| 70 |
+
- "docs/channels/telegram.md"
|
| 71 |
+
"channel: tlon":
|
| 72 |
+
- changed-files:
|
| 73 |
+
- any-glob-to-any-file:
|
| 74 |
+
- "extensions/tlon/**"
|
| 75 |
+
- "docs/channels/tlon.md"
|
| 76 |
+
"channel: voice-call":
|
| 77 |
+
- changed-files:
|
| 78 |
+
- any-glob-to-any-file:
|
| 79 |
+
- "extensions/voice-call/**"
|
| 80 |
+
"channel: whatsapp-web":
|
| 81 |
+
- changed-files:
|
| 82 |
+
- any-glob-to-any-file:
|
| 83 |
+
- "src/web/**"
|
| 84 |
+
- "extensions/whatsapp/**"
|
| 85 |
+
- "docs/channels/whatsapp.md"
|
| 86 |
+
"channel: zalo":
|
| 87 |
+
- changed-files:
|
| 88 |
+
- any-glob-to-any-file:
|
| 89 |
+
- "extensions/zalo/**"
|
| 90 |
+
- "docs/channels/zalo.md"
|
| 91 |
+
"channel: zalouser":
|
| 92 |
+
- changed-files:
|
| 93 |
+
- any-glob-to-any-file:
|
| 94 |
+
- "extensions/zalouser/**"
|
| 95 |
+
- "docs/channels/zalouser.md"
|
| 96 |
+
|
| 97 |
+
"app: android":
|
| 98 |
+
- changed-files:
|
| 99 |
+
- any-glob-to-any-file:
|
| 100 |
+
- "apps/android/**"
|
| 101 |
+
- "docs/platforms/android.md"
|
| 102 |
+
"app: ios":
|
| 103 |
+
- changed-files:
|
| 104 |
+
- any-glob-to-any-file:
|
| 105 |
+
- "apps/ios/**"
|
| 106 |
+
- "docs/platforms/ios.md"
|
| 107 |
+
"app: macos":
|
| 108 |
+
- changed-files:
|
| 109 |
+
- any-glob-to-any-file:
|
| 110 |
+
- "apps/macos/**"
|
| 111 |
+
- "docs/platforms/macos.md"
|
| 112 |
+
- "docs/platforms/mac/**"
|
| 113 |
+
"app: web-ui":
|
| 114 |
+
- changed-files:
|
| 115 |
+
- any-glob-to-any-file:
|
| 116 |
+
- "ui/**"
|
| 117 |
+
- "src/gateway/control-ui.ts"
|
| 118 |
+
- "src/gateway/control-ui-shared.ts"
|
| 119 |
+
- "src/gateway/protocol/**"
|
| 120 |
+
- "src/gateway/server-methods/chat.ts"
|
| 121 |
+
- "src/infra/control-ui-assets.ts"
|
| 122 |
+
|
| 123 |
+
"gateway":
|
| 124 |
+
- changed-files:
|
| 125 |
+
- any-glob-to-any-file:
|
| 126 |
+
- "src/gateway/**"
|
| 127 |
+
- "src/daemon/**"
|
| 128 |
+
- "docs/gateway/**"
|
| 129 |
+
|
| 130 |
+
"docs":
|
| 131 |
+
- changed-files:
|
| 132 |
+
- any-glob-to-any-file:
|
| 133 |
+
- "docs/**"
|
| 134 |
+
- "docs.acp.md"
|
| 135 |
+
|
| 136 |
+
"cli":
|
| 137 |
+
- changed-files:
|
| 138 |
+
- any-glob-to-any-file:
|
| 139 |
+
- "src/cli/**"
|
| 140 |
+
|
| 141 |
+
"commands":
|
| 142 |
+
- changed-files:
|
| 143 |
+
- any-glob-to-any-file:
|
| 144 |
+
- "src/commands/**"
|
| 145 |
+
|
| 146 |
+
"scripts":
|
| 147 |
+
- changed-files:
|
| 148 |
+
- any-glob-to-any-file:
|
| 149 |
+
- "scripts/**"
|
| 150 |
+
|
| 151 |
+
"docker":
|
| 152 |
+
- changed-files:
|
| 153 |
+
- any-glob-to-any-file:
|
| 154 |
+
- "Dockerfile"
|
| 155 |
+
- "Dockerfile.*"
|
| 156 |
+
- "docker-compose.yml"
|
| 157 |
+
- "docker-setup.sh"
|
| 158 |
+
- ".dockerignore"
|
| 159 |
+
- "scripts/**/*docker*"
|
| 160 |
+
- "scripts/**/Dockerfile*"
|
| 161 |
+
- "scripts/sandbox-*.sh"
|
| 162 |
+
- "src/agents/sandbox*.ts"
|
| 163 |
+
- "src/commands/sandbox*.ts"
|
| 164 |
+
- "src/cli/sandbox-cli.ts"
|
| 165 |
+
- "src/docker-setup.test.ts"
|
| 166 |
+
- "src/config/**/*sandbox*"
|
| 167 |
+
- "docs/cli/sandbox.md"
|
| 168 |
+
- "docs/gateway/sandbox*.md"
|
| 169 |
+
- "docs/install/docker.md"
|
| 170 |
+
- "docs/multi-agent-sandbox-tools.md"
|
| 171 |
+
|
| 172 |
+
"agents":
|
| 173 |
+
- changed-files:
|
| 174 |
+
- any-glob-to-any-file:
|
| 175 |
+
- "src/agents/**"
|
| 176 |
+
|
| 177 |
+
"security":
|
| 178 |
+
- changed-files:
|
| 179 |
+
- any-glob-to-any-file:
|
| 180 |
+
- "docs/cli/security.md"
|
| 181 |
+
- "docs/gateway/security.md"
|
| 182 |
+
|
| 183 |
+
"extensions: copilot-proxy":
|
| 184 |
+
- changed-files:
|
| 185 |
+
- any-glob-to-any-file:
|
| 186 |
+
- "extensions/copilot-proxy/**"
|
| 187 |
+
"extensions: diagnostics-otel":
|
| 188 |
+
- changed-files:
|
| 189 |
+
- any-glob-to-any-file:
|
| 190 |
+
- "extensions/diagnostics-otel/**"
|
| 191 |
+
"extensions: google-antigravity-auth":
|
| 192 |
+
- changed-files:
|
| 193 |
+
- any-glob-to-any-file:
|
| 194 |
+
- "extensions/google-antigravity-auth/**"
|
| 195 |
+
"extensions: google-gemini-cli-auth":
|
| 196 |
+
- changed-files:
|
| 197 |
+
- any-glob-to-any-file:
|
| 198 |
+
- "extensions/google-gemini-cli-auth/**"
|
| 199 |
+
"extensions: llm-task":
|
| 200 |
+
- changed-files:
|
| 201 |
+
- any-glob-to-any-file:
|
| 202 |
+
- "extensions/llm-task/**"
|
| 203 |
+
"extensions: lobster":
|
| 204 |
+
- changed-files:
|
| 205 |
+
- any-glob-to-any-file:
|
| 206 |
+
- "extensions/lobster/**"
|
| 207 |
+
"extensions: memory-core":
|
| 208 |
+
- changed-files:
|
| 209 |
+
- any-glob-to-any-file:
|
| 210 |
+
- "extensions/memory-core/**"
|
| 211 |
+
"extensions: memory-lancedb":
|
| 212 |
+
- changed-files:
|
| 213 |
+
- any-glob-to-any-file:
|
| 214 |
+
- "extensions/memory-lancedb/**"
|
| 215 |
+
"extensions: open-prose":
|
| 216 |
+
- changed-files:
|
| 217 |
+
- any-glob-to-any-file:
|
| 218 |
+
- "extensions/open-prose/**"
|
| 219 |
+
"extensions: qwen-portal-auth":
|
| 220 |
+
- changed-files:
|
| 221 |
+
- any-glob-to-any-file:
|
| 222 |
+
- "extensions/qwen-portal-auth/**"
|
.github/workflows/auto-response.yml
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
name: Auto response
|
| 2 |
+
|
| 3 |
+
on:
|
| 4 |
+
issues:
|
| 5 |
+
types: [labeled]
|
| 6 |
+
pull_request_target:
|
| 7 |
+
types: [labeled]
|
| 8 |
+
|
| 9 |
+
permissions:
|
| 10 |
+
issues: write
|
| 11 |
+
pull-requests: write
|
| 12 |
+
|
| 13 |
+
jobs:
|
| 14 |
+
auto-response:
|
| 15 |
+
runs-on: ubuntu-latest
|
| 16 |
+
steps:
|
| 17 |
+
- uses: actions/create-github-app-token@v1
|
| 18 |
+
id: app-token
|
| 19 |
+
with:
|
| 20 |
+
app-id: "2729701"
|
| 21 |
+
private-key: ${{ secrets.GH_APP_PRIVATE_KEY }}
|
| 22 |
+
- name: Handle labeled items
|
| 23 |
+
uses: actions/github-script@v7
|
| 24 |
+
with:
|
| 25 |
+
github-token: ${{ steps.app-token.outputs.token }}
|
| 26 |
+
script: |
|
| 27 |
+
const rules = [
|
| 28 |
+
{
|
| 29 |
+
label: "skill-clawdhub",
|
| 30 |
+
close: true,
|
| 31 |
+
message:
|
| 32 |
+
"Thanks for the contribution! New skills should be published to Clawdhub for everyone to use. We’re keeping the core lean on skills, so I’m closing this out.",
|
| 33 |
+
},
|
| 34 |
+
];
|
| 35 |
+
|
| 36 |
+
const labelName = context.payload.label?.name;
|
| 37 |
+
if (!labelName) {
|
| 38 |
+
return;
|
| 39 |
+
}
|
| 40 |
+
|
| 41 |
+
const rule = rules.find((item) => item.label === labelName);
|
| 42 |
+
if (!rule) {
|
| 43 |
+
return;
|
| 44 |
+
}
|
| 45 |
+
|
| 46 |
+
const issueNumber = context.payload.issue?.number ?? context.payload.pull_request?.number;
|
| 47 |
+
if (!issueNumber) {
|
| 48 |
+
return;
|
| 49 |
+
}
|
| 50 |
+
|
| 51 |
+
await github.rest.issues.createComment({
|
| 52 |
+
owner: context.repo.owner,
|
| 53 |
+
repo: context.repo.repo,
|
| 54 |
+
issue_number: issueNumber,
|
| 55 |
+
body: rule.message,
|
| 56 |
+
});
|
| 57 |
+
|
| 58 |
+
if (rule.close) {
|
| 59 |
+
await github.rest.issues.update({
|
| 60 |
+
owner: context.repo.owner,
|
| 61 |
+
repo: context.repo.repo,
|
| 62 |
+
issue_number: issueNumber,
|
| 63 |
+
state: "closed",
|
| 64 |
+
});
|
| 65 |
+
}
|
.github/workflows/ci.yml
ADDED
|
@@ -0,0 +1,646 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
name: CI
|
| 2 |
+
|
| 3 |
+
on:
|
| 4 |
+
push:
|
| 5 |
+
pull_request:
|
| 6 |
+
|
| 7 |
+
jobs:
|
| 8 |
+
install-check:
|
| 9 |
+
runs-on: blacksmith-4vcpu-ubuntu-2404
|
| 10 |
+
steps:
|
| 11 |
+
- name: Checkout
|
| 12 |
+
uses: actions/checkout@v4
|
| 13 |
+
with:
|
| 14 |
+
submodules: false
|
| 15 |
+
|
| 16 |
+
- name: Checkout submodules (retry)
|
| 17 |
+
run: |
|
| 18 |
+
set -euo pipefail
|
| 19 |
+
git submodule sync --recursive
|
| 20 |
+
for attempt in 1 2 3 4 5; do
|
| 21 |
+
if git -c protocol.version=2 submodule update --init --force --depth=1 --recursive; then
|
| 22 |
+
exit 0
|
| 23 |
+
fi
|
| 24 |
+
echo "Submodule update failed (attempt $attempt/5). Retrying…"
|
| 25 |
+
sleep $((attempt * 10))
|
| 26 |
+
done
|
| 27 |
+
exit 1
|
| 28 |
+
|
| 29 |
+
- name: Setup Node.js
|
| 30 |
+
uses: actions/setup-node@v4
|
| 31 |
+
with:
|
| 32 |
+
node-version: 22.x
|
| 33 |
+
check-latest: true
|
| 34 |
+
|
| 35 |
+
- name: Setup pnpm (corepack retry)
|
| 36 |
+
run: |
|
| 37 |
+
set -euo pipefail
|
| 38 |
+
corepack enable
|
| 39 |
+
for attempt in 1 2 3; do
|
| 40 |
+
if corepack prepare pnpm@10.23.0 --activate; then
|
| 41 |
+
pnpm -v
|
| 42 |
+
exit 0
|
| 43 |
+
fi
|
| 44 |
+
echo "corepack prepare failed (attempt $attempt/3). Retrying..."
|
| 45 |
+
sleep $((attempt * 10))
|
| 46 |
+
done
|
| 47 |
+
exit 1
|
| 48 |
+
|
| 49 |
+
- name: Runtime versions
|
| 50 |
+
run: |
|
| 51 |
+
node -v
|
| 52 |
+
npm -v
|
| 53 |
+
pnpm -v
|
| 54 |
+
|
| 55 |
+
- name: Capture node path
|
| 56 |
+
run: echo "NODE_BIN=$(dirname \"$(node -p \"process.execPath\")\")" >> "$GITHUB_ENV"
|
| 57 |
+
|
| 58 |
+
- name: Install dependencies (frozen)
|
| 59 |
+
env:
|
| 60 |
+
CI: true
|
| 61 |
+
run: |
|
| 62 |
+
export PATH="$NODE_BIN:$PATH"
|
| 63 |
+
which node
|
| 64 |
+
node -v
|
| 65 |
+
pnpm -v
|
| 66 |
+
pnpm install --frozen-lockfile --ignore-scripts=false --config.engine-strict=false --config.enable-pre-post-scripts=true
|
| 67 |
+
|
| 68 |
+
checks:
|
| 69 |
+
runs-on: blacksmith-4vcpu-ubuntu-2404
|
| 70 |
+
strategy:
|
| 71 |
+
fail-fast: false
|
| 72 |
+
matrix:
|
| 73 |
+
include:
|
| 74 |
+
- runtime: node
|
| 75 |
+
task: lint
|
| 76 |
+
command: pnpm lint
|
| 77 |
+
- runtime: node
|
| 78 |
+
task: test
|
| 79 |
+
command: pnpm test
|
| 80 |
+
- runtime: node
|
| 81 |
+
task: build
|
| 82 |
+
command: pnpm build
|
| 83 |
+
- runtime: node
|
| 84 |
+
task: protocol
|
| 85 |
+
command: pnpm protocol:check
|
| 86 |
+
- runtime: node
|
| 87 |
+
task: format
|
| 88 |
+
command: pnpm format
|
| 89 |
+
- runtime: bun
|
| 90 |
+
task: test
|
| 91 |
+
command: bunx vitest run
|
| 92 |
+
- runtime: bun
|
| 93 |
+
task: build
|
| 94 |
+
command: bunx tsc -p tsconfig.json
|
| 95 |
+
steps:
|
| 96 |
+
- name: Checkout
|
| 97 |
+
uses: actions/checkout@v4
|
| 98 |
+
with:
|
| 99 |
+
submodules: false
|
| 100 |
+
|
| 101 |
+
- name: Checkout submodules (retry)
|
| 102 |
+
run: |
|
| 103 |
+
set -euo pipefail
|
| 104 |
+
git submodule sync --recursive
|
| 105 |
+
for attempt in 1 2 3 4 5; do
|
| 106 |
+
if git -c protocol.version=2 submodule update --init --force --depth=1 --recursive; then
|
| 107 |
+
exit 0
|
| 108 |
+
fi
|
| 109 |
+
echo "Submodule update failed (attempt $attempt/5). Retrying…"
|
| 110 |
+
sleep $((attempt * 10))
|
| 111 |
+
done
|
| 112 |
+
exit 1
|
| 113 |
+
|
| 114 |
+
- name: Setup Node.js
|
| 115 |
+
uses: actions/setup-node@v4
|
| 116 |
+
with:
|
| 117 |
+
node-version: 22.x
|
| 118 |
+
check-latest: true
|
| 119 |
+
|
| 120 |
+
- name: Setup pnpm (corepack retry)
|
| 121 |
+
run: |
|
| 122 |
+
set -euo pipefail
|
| 123 |
+
corepack enable
|
| 124 |
+
for attempt in 1 2 3; do
|
| 125 |
+
if corepack prepare pnpm@10.23.0 --activate; then
|
| 126 |
+
pnpm -v
|
| 127 |
+
exit 0
|
| 128 |
+
fi
|
| 129 |
+
echo "corepack prepare failed (attempt $attempt/3). Retrying..."
|
| 130 |
+
sleep $((attempt * 10))
|
| 131 |
+
done
|
| 132 |
+
exit 1
|
| 133 |
+
|
| 134 |
+
- name: Setup Bun
|
| 135 |
+
uses: oven-sh/setup-bun@v2
|
| 136 |
+
with:
|
| 137 |
+
bun-version: latest
|
| 138 |
+
|
| 139 |
+
- name: Runtime versions
|
| 140 |
+
run: |
|
| 141 |
+
node -v
|
| 142 |
+
npm -v
|
| 143 |
+
bun -v
|
| 144 |
+
pnpm -v
|
| 145 |
+
|
| 146 |
+
- name: Capture node path
|
| 147 |
+
run: echo "NODE_BIN=$(dirname \"$(node -p \"process.execPath\")\")" >> "$GITHUB_ENV"
|
| 148 |
+
|
| 149 |
+
- name: Install dependencies
|
| 150 |
+
env:
|
| 151 |
+
CI: true
|
| 152 |
+
run: |
|
| 153 |
+
export PATH="$NODE_BIN:$PATH"
|
| 154 |
+
which node
|
| 155 |
+
node -v
|
| 156 |
+
pnpm -v
|
| 157 |
+
pnpm install --frozen-lockfile --ignore-scripts=false --config.engine-strict=false --config.enable-pre-post-scripts=true || pnpm install --frozen-lockfile --ignore-scripts=false --config.engine-strict=false --config.enable-pre-post-scripts=true
|
| 158 |
+
|
| 159 |
+
- name: Run ${{ matrix.task }} (${{ matrix.runtime }})
|
| 160 |
+
run: ${{ matrix.command }}
|
| 161 |
+
|
| 162 |
+
secrets:
|
| 163 |
+
runs-on: blacksmith-4vcpu-ubuntu-2404
|
| 164 |
+
steps:
|
| 165 |
+
- name: Checkout
|
| 166 |
+
uses: actions/checkout@v4
|
| 167 |
+
with:
|
| 168 |
+
submodules: false
|
| 169 |
+
|
| 170 |
+
- name: Setup Python
|
| 171 |
+
uses: actions/setup-python@v5
|
| 172 |
+
with:
|
| 173 |
+
python-version: "3.12"
|
| 174 |
+
|
| 175 |
+
- name: Install detect-secrets
|
| 176 |
+
run: |
|
| 177 |
+
python -m pip install --upgrade pip
|
| 178 |
+
python -m pip install detect-secrets==1.5.0
|
| 179 |
+
|
| 180 |
+
- name: Detect secrets
|
| 181 |
+
run: |
|
| 182 |
+
if ! detect-secrets scan --baseline .secrets.baseline; then
|
| 183 |
+
echo "::error::Secret scanning failed. See docs/gateway/security.md#secret-scanning-detect-secrets"
|
| 184 |
+
exit 1
|
| 185 |
+
fi
|
| 186 |
+
|
| 187 |
+
checks-windows:
|
| 188 |
+
runs-on: blacksmith-4vcpu-windows-2025
|
| 189 |
+
env:
|
| 190 |
+
NODE_OPTIONS: --max-old-space-size=4096
|
| 191 |
+
defaults:
|
| 192 |
+
run:
|
| 193 |
+
shell: bash
|
| 194 |
+
strategy:
|
| 195 |
+
fail-fast: false
|
| 196 |
+
matrix:
|
| 197 |
+
include:
|
| 198 |
+
- runtime: node
|
| 199 |
+
task: lint
|
| 200 |
+
command: pnpm lint
|
| 201 |
+
- runtime: node
|
| 202 |
+
task: test
|
| 203 |
+
command: pnpm test
|
| 204 |
+
- runtime: node
|
| 205 |
+
task: build
|
| 206 |
+
command: pnpm build
|
| 207 |
+
- runtime: node
|
| 208 |
+
task: protocol
|
| 209 |
+
command: pnpm protocol:check
|
| 210 |
+
steps:
|
| 211 |
+
- name: Checkout
|
| 212 |
+
uses: actions/checkout@v4
|
| 213 |
+
with:
|
| 214 |
+
submodules: false
|
| 215 |
+
|
| 216 |
+
- name: Checkout submodules (retry)
|
| 217 |
+
run: |
|
| 218 |
+
set -euo pipefail
|
| 219 |
+
git submodule sync --recursive
|
| 220 |
+
for attempt in 1 2 3 4 5; do
|
| 221 |
+
if git -c protocol.version=2 submodule update --init --force --depth=1 --recursive; then
|
| 222 |
+
exit 0
|
| 223 |
+
fi
|
| 224 |
+
echo "Submodule update failed (attempt $attempt/5). Retrying…"
|
| 225 |
+
sleep $((attempt * 10))
|
| 226 |
+
done
|
| 227 |
+
exit 1
|
| 228 |
+
|
| 229 |
+
- name: Setup Node.js
|
| 230 |
+
uses: actions/setup-node@v4
|
| 231 |
+
with:
|
| 232 |
+
node-version: 22.x
|
| 233 |
+
check-latest: true
|
| 234 |
+
|
| 235 |
+
- name: Setup pnpm (corepack retry)
|
| 236 |
+
run: |
|
| 237 |
+
set -euo pipefail
|
| 238 |
+
corepack enable
|
| 239 |
+
for attempt in 1 2 3; do
|
| 240 |
+
if corepack prepare pnpm@10.23.0 --activate; then
|
| 241 |
+
pnpm -v
|
| 242 |
+
exit 0
|
| 243 |
+
fi
|
| 244 |
+
echo "corepack prepare failed (attempt $attempt/3). Retrying..."
|
| 245 |
+
sleep $((attempt * 10))
|
| 246 |
+
done
|
| 247 |
+
exit 1
|
| 248 |
+
|
| 249 |
+
- name: Setup Bun
|
| 250 |
+
uses: oven-sh/setup-bun@v2
|
| 251 |
+
with:
|
| 252 |
+
bun-version: latest
|
| 253 |
+
|
| 254 |
+
- name: Runtime versions
|
| 255 |
+
run: |
|
| 256 |
+
node -v
|
| 257 |
+
npm -v
|
| 258 |
+
bun -v
|
| 259 |
+
pnpm -v
|
| 260 |
+
|
| 261 |
+
- name: Capture node path
|
| 262 |
+
run: echo "NODE_BIN=$(dirname \"$(node -p \"process.execPath\")\")" >> "$GITHUB_ENV"
|
| 263 |
+
|
| 264 |
+
- name: Install dependencies
|
| 265 |
+
env:
|
| 266 |
+
CI: true
|
| 267 |
+
run: |
|
| 268 |
+
export PATH="$NODE_BIN:$PATH"
|
| 269 |
+
which node
|
| 270 |
+
node -v
|
| 271 |
+
pnpm -v
|
| 272 |
+
pnpm install --frozen-lockfile --ignore-scripts=false --config.engine-strict=false --config.enable-pre-post-scripts=true || pnpm install --frozen-lockfile --ignore-scripts=false --config.engine-strict=false --config.enable-pre-post-scripts=true
|
| 273 |
+
|
| 274 |
+
- name: Run ${{ matrix.task }} (${{ matrix.runtime }})
|
| 275 |
+
run: ${{ matrix.command }}
|
| 276 |
+
|
| 277 |
+
checks-macos:
|
| 278 |
+
if: github.event_name == 'pull_request'
|
| 279 |
+
runs-on: macos-latest
|
| 280 |
+
strategy:
|
| 281 |
+
fail-fast: false
|
| 282 |
+
matrix:
|
| 283 |
+
include:
|
| 284 |
+
- task: test
|
| 285 |
+
command: pnpm test
|
| 286 |
+
steps:
|
| 287 |
+
- name: Checkout
|
| 288 |
+
uses: actions/checkout@v4
|
| 289 |
+
with:
|
| 290 |
+
submodules: false
|
| 291 |
+
|
| 292 |
+
- name: Checkout submodules (retry)
|
| 293 |
+
run: |
|
| 294 |
+
set -euo pipefail
|
| 295 |
+
git submodule sync --recursive
|
| 296 |
+
for attempt in 1 2 3 4 5; do
|
| 297 |
+
if git -c protocol.version=2 submodule update --init --force --depth=1 --recursive; then
|
| 298 |
+
exit 0
|
| 299 |
+
fi
|
| 300 |
+
echo "Submodule update failed (attempt $attempt/5). Retrying…"
|
| 301 |
+
sleep $((attempt * 10))
|
| 302 |
+
done
|
| 303 |
+
exit 1
|
| 304 |
+
|
| 305 |
+
- name: Setup Node.js
|
| 306 |
+
uses: actions/setup-node@v4
|
| 307 |
+
with:
|
| 308 |
+
node-version: 22.x
|
| 309 |
+
check-latest: true
|
| 310 |
+
|
| 311 |
+
- name: Setup pnpm (corepack retry)
|
| 312 |
+
run: |
|
| 313 |
+
set -euo pipefail
|
| 314 |
+
corepack enable
|
| 315 |
+
for attempt in 1 2 3; do
|
| 316 |
+
if corepack prepare pnpm@10.23.0 --activate; then
|
| 317 |
+
pnpm -v
|
| 318 |
+
exit 0
|
| 319 |
+
fi
|
| 320 |
+
echo "corepack prepare failed (attempt $attempt/3). Retrying..."
|
| 321 |
+
sleep $((attempt * 10))
|
| 322 |
+
done
|
| 323 |
+
exit 1
|
| 324 |
+
|
| 325 |
+
- name: Runtime versions
|
| 326 |
+
run: |
|
| 327 |
+
node -v
|
| 328 |
+
npm -v
|
| 329 |
+
pnpm -v
|
| 330 |
+
|
| 331 |
+
- name: Capture node path
|
| 332 |
+
run: echo "NODE_BIN=$(dirname \"$(node -p \"process.execPath\")\")" >> "$GITHUB_ENV"
|
| 333 |
+
|
| 334 |
+
- name: Install dependencies
|
| 335 |
+
env:
|
| 336 |
+
CI: true
|
| 337 |
+
run: |
|
| 338 |
+
export PATH="$NODE_BIN:$PATH"
|
| 339 |
+
which node
|
| 340 |
+
node -v
|
| 341 |
+
pnpm -v
|
| 342 |
+
pnpm install --frozen-lockfile --ignore-scripts=false --config.engine-strict=false --config.enable-pre-post-scripts=true || pnpm install --frozen-lockfile --ignore-scripts=false --config.engine-strict=false --config.enable-pre-post-scripts=true
|
| 343 |
+
|
| 344 |
+
- name: Run ${{ matrix.task }}
|
| 345 |
+
env:
|
| 346 |
+
NODE_OPTIONS: --max-old-space-size=4096
|
| 347 |
+
run: ${{ matrix.command }}
|
| 348 |
+
|
| 349 |
+
macos-app:
|
| 350 |
+
if: github.event_name == 'pull_request'
|
| 351 |
+
runs-on: macos-latest
|
| 352 |
+
strategy:
|
| 353 |
+
fail-fast: false
|
| 354 |
+
matrix:
|
| 355 |
+
include:
|
| 356 |
+
- task: lint
|
| 357 |
+
command: |
|
| 358 |
+
swiftlint --config .swiftlint.yml
|
| 359 |
+
swiftformat --lint apps/macos/Sources --config .swiftformat
|
| 360 |
+
- task: build
|
| 361 |
+
command: |
|
| 362 |
+
set -euo pipefail
|
| 363 |
+
for attempt in 1 2 3; do
|
| 364 |
+
if swift build --package-path apps/macos --configuration release; then
|
| 365 |
+
exit 0
|
| 366 |
+
fi
|
| 367 |
+
echo "swift build failed (attempt $attempt/3). Retrying…"
|
| 368 |
+
sleep $((attempt * 20))
|
| 369 |
+
done
|
| 370 |
+
exit 1
|
| 371 |
+
- task: test
|
| 372 |
+
command: |
|
| 373 |
+
set -euo pipefail
|
| 374 |
+
for attempt in 1 2 3; do
|
| 375 |
+
if swift test --package-path apps/macos --parallel --enable-code-coverage --show-codecov-path; then
|
| 376 |
+
exit 0
|
| 377 |
+
fi
|
| 378 |
+
echo "swift test failed (attempt $attempt/3). Retrying…"
|
| 379 |
+
sleep $((attempt * 20))
|
| 380 |
+
done
|
| 381 |
+
exit 1
|
| 382 |
+
steps:
|
| 383 |
+
- name: Checkout
|
| 384 |
+
uses: actions/checkout@v4
|
| 385 |
+
with:
|
| 386 |
+
submodules: false
|
| 387 |
+
|
| 388 |
+
- name: Checkout submodules (retry)
|
| 389 |
+
run: |
|
| 390 |
+
set -euo pipefail
|
| 391 |
+
git submodule sync --recursive
|
| 392 |
+
for attempt in 1 2 3 4 5; do
|
| 393 |
+
if git -c protocol.version=2 submodule update --init --force --depth=1 --recursive; then
|
| 394 |
+
exit 0
|
| 395 |
+
fi
|
| 396 |
+
echo "Submodule update failed (attempt $attempt/5). Retrying…"
|
| 397 |
+
sleep $((attempt * 10))
|
| 398 |
+
done
|
| 399 |
+
exit 1
|
| 400 |
+
|
| 401 |
+
- name: Select Xcode 26.1
|
| 402 |
+
run: |
|
| 403 |
+
sudo xcode-select -s /Applications/Xcode_26.1.app
|
| 404 |
+
xcodebuild -version
|
| 405 |
+
|
| 406 |
+
- name: Install XcodeGen / SwiftLint / SwiftFormat
|
| 407 |
+
run: |
|
| 408 |
+
brew install xcodegen swiftlint swiftformat
|
| 409 |
+
|
| 410 |
+
- name: Show toolchain
|
| 411 |
+
run: |
|
| 412 |
+
sw_vers
|
| 413 |
+
xcodebuild -version
|
| 414 |
+
swift --version
|
| 415 |
+
|
| 416 |
+
- name: Run ${{ matrix.task }}
|
| 417 |
+
run: ${{ matrix.command }}
|
| 418 |
+
ios:
|
| 419 |
+
if: false # ignore iOS in CI for now
|
| 420 |
+
runs-on: macos-latest
|
| 421 |
+
steps:
|
| 422 |
+
- name: Checkout
|
| 423 |
+
uses: actions/checkout@v4
|
| 424 |
+
with:
|
| 425 |
+
submodules: false
|
| 426 |
+
|
| 427 |
+
- name: Checkout submodules (retry)
|
| 428 |
+
run: |
|
| 429 |
+
set -euo pipefail
|
| 430 |
+
git submodule sync --recursive
|
| 431 |
+
for attempt in 1 2 3 4 5; do
|
| 432 |
+
if git -c protocol.version=2 submodule update --init --force --depth=1 --recursive; then
|
| 433 |
+
exit 0
|
| 434 |
+
fi
|
| 435 |
+
echo "Submodule update failed (attempt $attempt/5). Retrying…"
|
| 436 |
+
sleep $((attempt * 10))
|
| 437 |
+
done
|
| 438 |
+
exit 1
|
| 439 |
+
|
| 440 |
+
- name: Select Xcode 26.1
|
| 441 |
+
run: |
|
| 442 |
+
sudo xcode-select -s /Applications/Xcode_26.1.app
|
| 443 |
+
xcodebuild -version
|
| 444 |
+
|
| 445 |
+
- name: Install XcodeGen
|
| 446 |
+
run: brew install xcodegen
|
| 447 |
+
|
| 448 |
+
- name: Install SwiftLint / SwiftFormat
|
| 449 |
+
run: brew install swiftlint swiftformat
|
| 450 |
+
|
| 451 |
+
- name: Show toolchain
|
| 452 |
+
run: |
|
| 453 |
+
sw_vers
|
| 454 |
+
xcodebuild -version
|
| 455 |
+
swift --version
|
| 456 |
+
|
| 457 |
+
- name: Generate iOS project
|
| 458 |
+
run: |
|
| 459 |
+
cd apps/ios
|
| 460 |
+
xcodegen generate
|
| 461 |
+
|
| 462 |
+
- name: iOS tests
|
| 463 |
+
run: |
|
| 464 |
+
set -euo pipefail
|
| 465 |
+
RESULT_BUNDLE_PATH="$RUNNER_TEMP/Clawdis-iOS.xcresult"
|
| 466 |
+
DEST_ID="$(
|
| 467 |
+
python3 - <<'PY'
|
| 468 |
+
import json
|
| 469 |
+
import subprocess
|
| 470 |
+
import sys
|
| 471 |
+
import uuid
|
| 472 |
+
|
| 473 |
+
def sh(args: list[str]) -> str:
|
| 474 |
+
return subprocess.check_output(args, text=True).strip()
|
| 475 |
+
|
| 476 |
+
# Prefer an already-created iPhone simulator if it exists.
|
| 477 |
+
devices = json.loads(sh(["xcrun", "simctl", "list", "devices", "-j"]))
|
| 478 |
+
candidates: list[tuple[str, str]] = []
|
| 479 |
+
for runtime, devs in (devices.get("devices") or {}).items():
|
| 480 |
+
for dev in devs or []:
|
| 481 |
+
if not dev.get("isAvailable"):
|
| 482 |
+
continue
|
| 483 |
+
name = str(dev.get("name") or "")
|
| 484 |
+
udid = str(dev.get("udid") or "")
|
| 485 |
+
if not udid or not name.startswith("iPhone"):
|
| 486 |
+
continue
|
| 487 |
+
candidates.append((name, udid))
|
| 488 |
+
|
| 489 |
+
candidates.sort(key=lambda it: (0 if "iPhone 16" in it[0] else 1, it[0]))
|
| 490 |
+
if candidates:
|
| 491 |
+
print(candidates[0][1])
|
| 492 |
+
sys.exit(0)
|
| 493 |
+
|
| 494 |
+
# Otherwise, create one from the newest available iOS runtime.
|
| 495 |
+
runtimes = json.loads(sh(["xcrun", "simctl", "list", "runtimes", "-j"])).get("runtimes") or []
|
| 496 |
+
ios = [rt for rt in runtimes if rt.get("platform") == "iOS" and rt.get("isAvailable")]
|
| 497 |
+
if not ios:
|
| 498 |
+
print("No available iOS runtimes found.", file=sys.stderr)
|
| 499 |
+
sys.exit(1)
|
| 500 |
+
|
| 501 |
+
def version_key(rt: dict) -> tuple[int, ...]:
|
| 502 |
+
parts: list[int] = []
|
| 503 |
+
for p in str(rt.get("version") or "0").split("."):
|
| 504 |
+
try:
|
| 505 |
+
parts.append(int(p))
|
| 506 |
+
except ValueError:
|
| 507 |
+
parts.append(0)
|
| 508 |
+
return tuple(parts)
|
| 509 |
+
|
| 510 |
+
ios.sort(key=version_key, reverse=True)
|
| 511 |
+
runtime = ios[0]
|
| 512 |
+
runtime_id = str(runtime.get("identifier") or "")
|
| 513 |
+
if not runtime_id:
|
| 514 |
+
print("Missing iOS runtime identifier.", file=sys.stderr)
|
| 515 |
+
sys.exit(1)
|
| 516 |
+
|
| 517 |
+
supported = runtime.get("supportedDeviceTypes") or []
|
| 518 |
+
iphones = [dt for dt in supported if dt.get("productFamily") == "iPhone"]
|
| 519 |
+
if not iphones:
|
| 520 |
+
print("No iPhone device types for iOS runtime.", file=sys.stderr)
|
| 521 |
+
sys.exit(1)
|
| 522 |
+
|
| 523 |
+
iphones.sort(
|
| 524 |
+
key=lambda dt: (
|
| 525 |
+
0 if "iPhone 16" in str(dt.get("name") or "") else 1,
|
| 526 |
+
str(dt.get("name") or ""),
|
| 527 |
+
)
|
| 528 |
+
)
|
| 529 |
+
device_type_id = str(iphones[0].get("identifier") or "")
|
| 530 |
+
if not device_type_id:
|
| 531 |
+
print("Missing iPhone device type identifier.", file=sys.stderr)
|
| 532 |
+
sys.exit(1)
|
| 533 |
+
|
| 534 |
+
sim_name = f"CI iPhone {uuid.uuid4().hex[:8]}"
|
| 535 |
+
udid = sh(["xcrun", "simctl", "create", sim_name, device_type_id, runtime_id])
|
| 536 |
+
if not udid:
|
| 537 |
+
print("Failed to create iPhone simulator.", file=sys.stderr)
|
| 538 |
+
sys.exit(1)
|
| 539 |
+
print(udid)
|
| 540 |
+
PY
|
| 541 |
+
)"
|
| 542 |
+
echo "Using iOS Simulator id: $DEST_ID"
|
| 543 |
+
xcodebuild test \
|
| 544 |
+
-project apps/ios/Clawdis.xcodeproj \
|
| 545 |
+
-scheme Clawdis \
|
| 546 |
+
-destination "platform=iOS Simulator,id=$DEST_ID" \
|
| 547 |
+
-resultBundlePath "$RESULT_BUNDLE_PATH" \
|
| 548 |
+
-enableCodeCoverage YES
|
| 549 |
+
|
| 550 |
+
- name: iOS coverage summary
|
| 551 |
+
run: |
|
| 552 |
+
set -euo pipefail
|
| 553 |
+
RESULT_BUNDLE_PATH="$RUNNER_TEMP/Clawdis-iOS.xcresult"
|
| 554 |
+
xcrun xccov view --report --only-targets "$RESULT_BUNDLE_PATH"
|
| 555 |
+
|
| 556 |
+
- name: iOS coverage gate (43%)
|
| 557 |
+
run: |
|
| 558 |
+
set -euo pipefail
|
| 559 |
+
RESULT_BUNDLE_PATH="$RUNNER_TEMP/Clawdis-iOS.xcresult"
|
| 560 |
+
RESULT_BUNDLE_PATH="$RESULT_BUNDLE_PATH" python3 - <<'PY'
|
| 561 |
+
import json
|
| 562 |
+
import os
|
| 563 |
+
import subprocess
|
| 564 |
+
import sys
|
| 565 |
+
|
| 566 |
+
target_name = "Clawdis.app"
|
| 567 |
+
minimum = 0.43
|
| 568 |
+
|
| 569 |
+
report = json.loads(
|
| 570 |
+
subprocess.check_output(
|
| 571 |
+
["xcrun", "xccov", "view", "--report", "--json", os.environ["RESULT_BUNDLE_PATH"]],
|
| 572 |
+
text=True,
|
| 573 |
+
)
|
| 574 |
+
)
|
| 575 |
+
|
| 576 |
+
target_coverage = None
|
| 577 |
+
for target in report.get("targets", []):
|
| 578 |
+
if target.get("name") == target_name:
|
| 579 |
+
target_coverage = float(target["lineCoverage"])
|
| 580 |
+
break
|
| 581 |
+
|
| 582 |
+
if target_coverage is None:
|
| 583 |
+
print(f"Could not find coverage for target: {target_name}")
|
| 584 |
+
sys.exit(1)
|
| 585 |
+
|
| 586 |
+
print(f"{target_name} line coverage: {target_coverage * 100:.2f}% (min {minimum * 100:.2f}%)")
|
| 587 |
+
if target_coverage + 1e-12 < minimum:
|
| 588 |
+
sys.exit(1)
|
| 589 |
+
PY
|
| 590 |
+
|
| 591 |
+
android:
|
| 592 |
+
runs-on: blacksmith-4vcpu-ubuntu-2404
|
| 593 |
+
strategy:
|
| 594 |
+
fail-fast: false
|
| 595 |
+
matrix:
|
| 596 |
+
include:
|
| 597 |
+
- task: test
|
| 598 |
+
command: ./gradlew --no-daemon :app:testDebugUnitTest
|
| 599 |
+
- task: build
|
| 600 |
+
command: ./gradlew --no-daemon :app:assembleDebug
|
| 601 |
+
steps:
|
| 602 |
+
- name: Checkout
|
| 603 |
+
uses: actions/checkout@v4
|
| 604 |
+
with:
|
| 605 |
+
submodules: false
|
| 606 |
+
|
| 607 |
+
- name: Checkout submodules (retry)
|
| 608 |
+
run: |
|
| 609 |
+
set -euo pipefail
|
| 610 |
+
git submodule sync --recursive
|
| 611 |
+
for attempt in 1 2 3 4 5; do
|
| 612 |
+
if git -c protocol.version=2 submodule update --init --force --depth=1 --recursive; then
|
| 613 |
+
exit 0
|
| 614 |
+
fi
|
| 615 |
+
echo "Submodule update failed (attempt $attempt/5). Retrying…"
|
| 616 |
+
sleep $((attempt * 10))
|
| 617 |
+
done
|
| 618 |
+
exit 1
|
| 619 |
+
|
| 620 |
+
- name: Setup Java
|
| 621 |
+
uses: actions/setup-java@v4
|
| 622 |
+
with:
|
| 623 |
+
distribution: temurin
|
| 624 |
+
java-version: 21
|
| 625 |
+
|
| 626 |
+
- name: Setup Android SDK
|
| 627 |
+
uses: android-actions/setup-android@v3
|
| 628 |
+
with:
|
| 629 |
+
accept-android-sdk-licenses: false
|
| 630 |
+
|
| 631 |
+
- name: Setup Gradle
|
| 632 |
+
uses: gradle/actions/setup-gradle@v4
|
| 633 |
+
with:
|
| 634 |
+
gradle-version: 8.11.1
|
| 635 |
+
|
| 636 |
+
- name: Install Android SDK packages
|
| 637 |
+
run: |
|
| 638 |
+
yes | sdkmanager --licenses >/dev/null
|
| 639 |
+
sdkmanager --install \
|
| 640 |
+
"platform-tools" \
|
| 641 |
+
"platforms;android-36" \
|
| 642 |
+
"build-tools;36.0.0"
|
| 643 |
+
|
| 644 |
+
- name: Run Android ${{ matrix.task }}
|
| 645 |
+
working-directory: apps/android
|
| 646 |
+
run: ${{ matrix.command }}
|
.github/workflows/docker-release.yml
ADDED
|
@@ -0,0 +1,143 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
name: Docker Release
|
| 2 |
+
|
| 3 |
+
on:
|
| 4 |
+
push:
|
| 5 |
+
branches:
|
| 6 |
+
- main
|
| 7 |
+
tags:
|
| 8 |
+
- "v*"
|
| 9 |
+
|
| 10 |
+
env:
|
| 11 |
+
REGISTRY: ghcr.io
|
| 12 |
+
IMAGE_NAME: ${{ github.repository }}
|
| 13 |
+
|
| 14 |
+
jobs:
|
| 15 |
+
# Build amd64 image
|
| 16 |
+
build-amd64:
|
| 17 |
+
runs-on: ubuntu-latest
|
| 18 |
+
permissions:
|
| 19 |
+
packages: write
|
| 20 |
+
contents: read
|
| 21 |
+
outputs:
|
| 22 |
+
image-digest: ${{ steps.build.outputs.digest }}
|
| 23 |
+
image-metadata: ${{ steps.meta.outputs.json }}
|
| 24 |
+
steps:
|
| 25 |
+
- name: Checkout
|
| 26 |
+
uses: actions/checkout@v4
|
| 27 |
+
|
| 28 |
+
- name: Set up Docker Buildx
|
| 29 |
+
uses: docker/setup-buildx-action@v3
|
| 30 |
+
|
| 31 |
+
- name: Login to GitHub Container Registry
|
| 32 |
+
uses: docker/login-action@v3
|
| 33 |
+
with:
|
| 34 |
+
registry: ${{ env.REGISTRY }}
|
| 35 |
+
username: ${{ github.repository_owner }}
|
| 36 |
+
password: ${{ secrets.GITHUB_TOKEN }}
|
| 37 |
+
|
| 38 |
+
- name: Extract metadata
|
| 39 |
+
id: meta
|
| 40 |
+
uses: docker/metadata-action@v5
|
| 41 |
+
with:
|
| 42 |
+
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
| 43 |
+
tags: |
|
| 44 |
+
type=ref,event=branch
|
| 45 |
+
type=semver,pattern={{version}}
|
| 46 |
+
type=semver,pattern={{version}},suffix=-amd64
|
| 47 |
+
type=semver,pattern={{version}},suffix=-arm64
|
| 48 |
+
type=ref,event=branch,suffix=-amd64
|
| 49 |
+
type=ref,event=branch,suffix=-arm64
|
| 50 |
+
|
| 51 |
+
- name: Build and push amd64 image
|
| 52 |
+
id: build
|
| 53 |
+
uses: docker/build-push-action@v6
|
| 54 |
+
with:
|
| 55 |
+
context: .
|
| 56 |
+
platforms: linux/amd64
|
| 57 |
+
labels: ${{ steps.meta.outputs.labels }}
|
| 58 |
+
tags: ${{ steps.meta.outputs.tags }}
|
| 59 |
+
cache-from: type=gha
|
| 60 |
+
cache-to: type=gha,mode=max
|
| 61 |
+
provenance: false
|
| 62 |
+
push: true
|
| 63 |
+
|
| 64 |
+
# Build arm64 image
|
| 65 |
+
build-arm64:
|
| 66 |
+
runs-on: ubuntu-24.04-arm
|
| 67 |
+
permissions:
|
| 68 |
+
packages: write
|
| 69 |
+
contents: read
|
| 70 |
+
outputs:
|
| 71 |
+
image-digest: ${{ steps.build.outputs.digest }}
|
| 72 |
+
image-metadata: ${{ steps.meta.outputs.json }}
|
| 73 |
+
steps:
|
| 74 |
+
- name: Checkout
|
| 75 |
+
uses: actions/checkout@v4
|
| 76 |
+
|
| 77 |
+
- name: Set up Docker Buildx
|
| 78 |
+
uses: docker/setup-buildx-action@v3
|
| 79 |
+
|
| 80 |
+
- name: Login to GitHub Container Registry
|
| 81 |
+
uses: docker/login-action@v3
|
| 82 |
+
with:
|
| 83 |
+
registry: ${{ env.REGISTRY }}
|
| 84 |
+
username: ${{ github.repository_owner }}
|
| 85 |
+
password: ${{ secrets.GITHUB_TOKEN }}
|
| 86 |
+
|
| 87 |
+
- name: Extract metadata
|
| 88 |
+
id: meta
|
| 89 |
+
uses: docker/metadata-action@v5
|
| 90 |
+
with:
|
| 91 |
+
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
| 92 |
+
tags: |
|
| 93 |
+
type=ref,event=branch
|
| 94 |
+
type=semver,pattern={{version}}
|
| 95 |
+
type=semver,pattern={{version}},suffix=-amd64
|
| 96 |
+
type=semver,pattern={{version}},suffix=-arm64
|
| 97 |
+
type=ref,event=branch,suffix=-amd64
|
| 98 |
+
type=ref,event=branch,suffix=-arm64
|
| 99 |
+
|
| 100 |
+
- name: Build and push arm64 image
|
| 101 |
+
id: build
|
| 102 |
+
uses: docker/build-push-action@v6
|
| 103 |
+
with:
|
| 104 |
+
context: .
|
| 105 |
+
platforms: linux/arm64
|
| 106 |
+
labels: ${{ steps.meta.outputs.labels }}
|
| 107 |
+
tags: ${{ steps.meta.outputs.tags }}
|
| 108 |
+
cache-from: type=gha
|
| 109 |
+
cache-to: type=gha,mode=max
|
| 110 |
+
provenance: false
|
| 111 |
+
push: true
|
| 112 |
+
|
| 113 |
+
# Create multi-platform manifest
|
| 114 |
+
create-manifest:
|
| 115 |
+
runs-on: ubuntu-latest
|
| 116 |
+
permissions:
|
| 117 |
+
packages: write
|
| 118 |
+
contents: read
|
| 119 |
+
needs: [build-amd64, build-arm64]
|
| 120 |
+
steps:
|
| 121 |
+
- name: Login to GitHub Container Registry
|
| 122 |
+
uses: docker/login-action@v3
|
| 123 |
+
with:
|
| 124 |
+
registry: ${{ env.REGISTRY }}
|
| 125 |
+
username: ${{ github.repository_owner }}
|
| 126 |
+
password: ${{ secrets.GITHUB_TOKEN }}
|
| 127 |
+
|
| 128 |
+
- name: Extract metadata for manifest
|
| 129 |
+
id: meta
|
| 130 |
+
uses: docker/metadata-action@v5
|
| 131 |
+
with:
|
| 132 |
+
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
| 133 |
+
tags: |
|
| 134 |
+
type=ref,event=branch
|
| 135 |
+
type=semver,pattern={{version}}
|
| 136 |
+
|
| 137 |
+
- name: Create and push manifest
|
| 138 |
+
run: |
|
| 139 |
+
docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
|
| 140 |
+
${{ needs.build-amd64.outputs.image-digest }} \
|
| 141 |
+
${{ needs.build-arm64.outputs.image-digest }}
|
| 142 |
+
env:
|
| 143 |
+
DOCKER_METADATA_OUTPUT_JSON: ${{ steps.meta.outputs.json }}
|
.github/workflows/install-smoke.yml
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
name: Install Smoke
|
| 2 |
+
|
| 3 |
+
on:
|
| 4 |
+
push:
|
| 5 |
+
branches: [main]
|
| 6 |
+
pull_request:
|
| 7 |
+
workflow_dispatch:
|
| 8 |
+
|
| 9 |
+
jobs:
|
| 10 |
+
install-smoke:
|
| 11 |
+
runs-on: ubuntu-latest
|
| 12 |
+
steps:
|
| 13 |
+
- name: Checkout CLI
|
| 14 |
+
uses: actions/checkout@v4
|
| 15 |
+
|
| 16 |
+
- name: Setup pnpm (corepack retry)
|
| 17 |
+
run: |
|
| 18 |
+
set -euo pipefail
|
| 19 |
+
corepack enable
|
| 20 |
+
for attempt in 1 2 3; do
|
| 21 |
+
if corepack prepare pnpm@10.23.0 --activate; then
|
| 22 |
+
pnpm -v
|
| 23 |
+
exit 0
|
| 24 |
+
fi
|
| 25 |
+
echo "corepack prepare failed (attempt $attempt/3). Retrying..."
|
| 26 |
+
sleep $((attempt * 10))
|
| 27 |
+
done
|
| 28 |
+
exit 1
|
| 29 |
+
|
| 30 |
+
- name: Install pnpm deps (minimal)
|
| 31 |
+
run: pnpm install --ignore-scripts --frozen-lockfile
|
| 32 |
+
|
| 33 |
+
- name: Run installer docker tests
|
| 34 |
+
env:
|
| 35 |
+
CLAWDBOT_INSTALL_URL: https://clawd.bot/install.sh
|
| 36 |
+
CLAWDBOT_INSTALL_CLI_URL: https://clawd.bot/install-cli.sh
|
| 37 |
+
CLAWDBOT_NO_ONBOARD: "1"
|
| 38 |
+
CLAWDBOT_INSTALL_SMOKE_SKIP_CLI: "1"
|
| 39 |
+
CLAWDBOT_INSTALL_SMOKE_SKIP_NONROOT: ${{ github.event_name == 'pull_request' && '1' || '0' }}
|
| 40 |
+
CLAWDBOT_INSTALL_SMOKE_PREVIOUS: "2026.1.11-4"
|
| 41 |
+
run: pnpm test:install:smoke
|
.github/workflows/labeler.yml
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
name: Labeler
|
| 2 |
+
|
| 3 |
+
on:
|
| 4 |
+
pull_request_target:
|
| 5 |
+
types: [opened, synchronize, reopened]
|
| 6 |
+
|
| 7 |
+
permissions:
|
| 8 |
+
contents: read
|
| 9 |
+
pull-requests: write
|
| 10 |
+
|
| 11 |
+
jobs:
|
| 12 |
+
label:
|
| 13 |
+
runs-on: ubuntu-latest
|
| 14 |
+
steps:
|
| 15 |
+
- uses: actions/create-github-app-token@v1
|
| 16 |
+
id: app-token
|
| 17 |
+
with:
|
| 18 |
+
app-id: "2729701"
|
| 19 |
+
private-key: ${{ secrets.GH_APP_PRIVATE_KEY }}
|
| 20 |
+
- uses: actions/labeler@v5
|
| 21 |
+
with:
|
| 22 |
+
configuration-path: .github/labeler.yml
|
| 23 |
+
repo-token: ${{ steps.app-token.outputs.token }}
|
| 24 |
+
sync-labels: true
|
.github/workflows/workflow-sanity.yml
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
name: Workflow Sanity
|
| 2 |
+
|
| 3 |
+
on:
|
| 4 |
+
pull_request:
|
| 5 |
+
push:
|
| 6 |
+
|
| 7 |
+
jobs:
|
| 8 |
+
no-tabs:
|
| 9 |
+
runs-on: ubuntu-latest
|
| 10 |
+
steps:
|
| 11 |
+
- name: Checkout
|
| 12 |
+
uses: actions/checkout@v4
|
| 13 |
+
|
| 14 |
+
- name: Fail on tabs in workflow files
|
| 15 |
+
run: |
|
| 16 |
+
python - <<'PY'
|
| 17 |
+
from __future__ import annotations
|
| 18 |
+
|
| 19 |
+
import pathlib
|
| 20 |
+
import sys
|
| 21 |
+
|
| 22 |
+
root = pathlib.Path(".github/workflows")
|
| 23 |
+
bad: list[str] = []
|
| 24 |
+
for path in sorted(root.rglob("*.yml")):
|
| 25 |
+
if b"\t" in path.read_bytes():
|
| 26 |
+
bad.append(str(path))
|
| 27 |
+
|
| 28 |
+
for path in sorted(root.rglob("*.yaml")):
|
| 29 |
+
if b"\t" in path.read_bytes():
|
| 30 |
+
bad.append(str(path))
|
| 31 |
+
|
| 32 |
+
if bad:
|
| 33 |
+
print("Tabs found in workflow file(s):")
|
| 34 |
+
for path in bad:
|
| 35 |
+
print(f"- {path}")
|
| 36 |
+
sys.exit(1)
|
| 37 |
+
PY
|
.gitignore
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
node_modules
|
| 2 |
+
**/node_modules/
|
| 3 |
+
.env
|
| 4 |
+
docker-compose.extra.yml
|
| 5 |
+
dist
|
| 6 |
+
*.bun-build
|
| 7 |
+
pnpm-lock.yaml
|
| 8 |
+
bun.lock
|
| 9 |
+
bun.lockb
|
| 10 |
+
coverage
|
| 11 |
+
.pnpm-store
|
| 12 |
+
.worktrees/
|
| 13 |
+
.DS_Store
|
| 14 |
+
**/.DS_Store
|
| 15 |
+
ui/src/ui/__screenshots__/
|
| 16 |
+
ui/playwright-report/
|
| 17 |
+
ui/test-results/
|
| 18 |
+
|
| 19 |
+
# Bun build artifacts
|
| 20 |
+
*.bun-build
|
| 21 |
+
apps/macos/.build/
|
| 22 |
+
apps/shared/ClawdbotKit/.build/
|
| 23 |
+
**/ModuleCache/
|
| 24 |
+
bin/
|
| 25 |
+
bin/clawdbot-mac
|
| 26 |
+
bin/docs-list
|
| 27 |
+
apps/macos/.build-local/
|
| 28 |
+
apps/macos/.swiftpm/
|
| 29 |
+
apps/shared/ClawdbotKit/.swiftpm/
|
| 30 |
+
Core/
|
| 31 |
+
apps/ios/*.xcodeproj/
|
| 32 |
+
apps/ios/*.xcworkspace/
|
| 33 |
+
apps/ios/.swiftpm/
|
| 34 |
+
vendor/
|
| 35 |
+
apps/ios/Clawdbot.xcodeproj/
|
| 36 |
+
apps/ios/Clawdbot.xcodeproj/**
|
| 37 |
+
apps/macos/.build/**
|
| 38 |
+
**/*.bun-build
|
| 39 |
+
apps/ios/*.xcfilelist
|
| 40 |
+
|
| 41 |
+
# Vendor build artifacts
|
| 42 |
+
vendor/a2ui/renderers/lit/dist/
|
| 43 |
+
src/canvas-host/a2ui/*.bundle.js
|
| 44 |
+
src/canvas-host/a2ui/*.map
|
| 45 |
+
.bundle.hash
|
| 46 |
+
|
| 47 |
+
# fastlane (iOS)
|
| 48 |
+
apps/ios/fastlane/README.md
|
| 49 |
+
apps/ios/fastlane/report.xml
|
| 50 |
+
apps/ios/fastlane/Preview.html
|
| 51 |
+
apps/ios/fastlane/screenshots/
|
| 52 |
+
apps/ios/fastlane/test_output/
|
| 53 |
+
apps/ios/fastlane/logs/
|
| 54 |
+
apps/ios/fastlane/.env
|
| 55 |
+
apps/ios/fastlane/report.xml
|
| 56 |
+
|
| 57 |
+
# fastlane build artifacts (local)
|
| 58 |
+
apps/ios/*.ipa
|
| 59 |
+
apps/ios/*.dSYM.zip
|
| 60 |
+
|
| 61 |
+
# provisioning profiles (local)
|
| 62 |
+
apps/ios/*.mobileprovision
|
| 63 |
+
.env
|
| 64 |
+
|
| 65 |
+
# Local untracked files
|
| 66 |
+
.local/
|
| 67 |
+
.vscode/
|
| 68 |
+
IDENTITY.md
|
| 69 |
+
USER.md
|
| 70 |
+
.tgz
|
| 71 |
+
|
| 72 |
+
# local tooling
|
| 73 |
+
.serena/
|
.npmrc
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
allow-build-scripts=@whiskeysockets/baileys,sharp,esbuild,protobufjs,fs-ext,node-pty,@lydell/node-pty,@matrix-org/matrix-sdk-crypto-nodejs
|
.oxfmtrc.jsonc
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"$schema": "./node_modules/oxfmt/configuration_schema.json",
|
| 3 |
+
"indentWidth": 2,
|
| 4 |
+
"printWidth": 100
|
| 5 |
+
}
|
.oxlintrc.json
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"$schema": "./node_modules/oxlint/configuration_schema.json",
|
| 3 |
+
"plugins": [
|
| 4 |
+
"unicorn",
|
| 5 |
+
"typescript",
|
| 6 |
+
"oxc"
|
| 7 |
+
],
|
| 8 |
+
"categories": {
|
| 9 |
+
"correctness": "error"
|
| 10 |
+
},
|
| 11 |
+
"ignorePatterns": ["src/canvas-host/a2ui/a2ui.bundle.js"]
|
| 12 |
+
}
|
.pre-commit-config.yaml
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Pre-commit hooks for clawdbot
|
| 2 |
+
# Install: prek install
|
| 3 |
+
# Run manually: prek run --all-files
|
| 4 |
+
#
|
| 5 |
+
# See https://pre-commit.com for more information
|
| 6 |
+
|
| 7 |
+
repos:
|
| 8 |
+
# Basic file hygiene
|
| 9 |
+
- repo: https://github.com/pre-commit/pre-commit-hooks
|
| 10 |
+
rev: v6.0.0
|
| 11 |
+
hooks:
|
| 12 |
+
- id: trailing-whitespace
|
| 13 |
+
exclude: '^(docs/|dist/|vendor/|.*\.snap$)'
|
| 14 |
+
- id: end-of-file-fixer
|
| 15 |
+
exclude: '^(docs/|dist/|vendor/|.*\.snap$)'
|
| 16 |
+
- id: check-yaml
|
| 17 |
+
args: [--allow-multiple-documents]
|
| 18 |
+
- id: check-added-large-files
|
| 19 |
+
args: [--maxkb=500]
|
| 20 |
+
- id: check-merge-conflict
|
| 21 |
+
|
| 22 |
+
# Secret detection (same as CI)
|
| 23 |
+
- repo: https://github.com/Yelp/detect-secrets
|
| 24 |
+
rev: v1.5.0
|
| 25 |
+
hooks:
|
| 26 |
+
- id: detect-secrets
|
| 27 |
+
args:
|
| 28 |
+
- --baseline
|
| 29 |
+
- .secrets.baseline
|
| 30 |
+
- --exclude-files
|
| 31 |
+
- '(^|/)(dist/|vendor/|pnpm-lock\.yaml$|\.detect-secrets\.cfg$)'
|
| 32 |
+
- --exclude-lines
|
| 33 |
+
- 'key_content\.include\?\("BEGIN PRIVATE KEY"\)'
|
| 34 |
+
- --exclude-lines
|
| 35 |
+
- 'case \.apiKeyEnv: "API key \(env var\)"'
|
| 36 |
+
- --exclude-lines
|
| 37 |
+
- 'case apikey = "apiKey"'
|
| 38 |
+
- --exclude-lines
|
| 39 |
+
- '"gateway\.remote\.password"'
|
| 40 |
+
- --exclude-lines
|
| 41 |
+
- '"gateway\.auth\.password"'
|
| 42 |
+
- --exclude-lines
|
| 43 |
+
- '"talk\.apiKey"'
|
| 44 |
+
- --exclude-lines
|
| 45 |
+
- '=== "string"'
|
| 46 |
+
- --exclude-lines
|
| 47 |
+
- 'typeof remote\?\.password === "string"'
|
| 48 |
+
|
| 49 |
+
# Shell script linting
|
| 50 |
+
- repo: https://github.com/koalaman/shellcheck-precommit
|
| 51 |
+
rev: v0.11.0
|
| 52 |
+
hooks:
|
| 53 |
+
- id: shellcheck
|
| 54 |
+
args: [--severity=error] # Only fail on errors, not warnings/info
|
| 55 |
+
# Exclude vendor and scripts with embedded code or known issues
|
| 56 |
+
exclude: '^(vendor/|scripts/e2e/)'
|
| 57 |
+
|
| 58 |
+
# GitHub Actions linting
|
| 59 |
+
- repo: https://github.com/rhysd/actionlint
|
| 60 |
+
rev: v1.7.10
|
| 61 |
+
hooks:
|
| 62 |
+
- id: actionlint
|
| 63 |
+
|
| 64 |
+
# GitHub Actions security audit
|
| 65 |
+
- repo: https://github.com/zizmorcore/zizmor-pre-commit
|
| 66 |
+
rev: v1.22.0
|
| 67 |
+
hooks:
|
| 68 |
+
- id: zizmor
|
| 69 |
+
args: [--persona=regular, --min-severity=medium, --min-confidence=medium]
|
| 70 |
+
exclude: '^(vendor/|Swabble/)'
|
| 71 |
+
|
| 72 |
+
# Project checks (same commands as CI)
|
| 73 |
+
- repo: local
|
| 74 |
+
hooks:
|
| 75 |
+
# oxlint --type-aware src test
|
| 76 |
+
- id: oxlint
|
| 77 |
+
name: oxlint
|
| 78 |
+
entry: scripts/pre-commit/run-node-tool.sh oxlint --type-aware src test
|
| 79 |
+
language: system
|
| 80 |
+
pass_filenames: false
|
| 81 |
+
types_or: [javascript, jsx, ts, tsx]
|
| 82 |
+
|
| 83 |
+
# oxfmt --check src test
|
| 84 |
+
- id: oxfmt
|
| 85 |
+
name: oxfmt
|
| 86 |
+
entry: scripts/pre-commit/run-node-tool.sh oxfmt --check src test
|
| 87 |
+
language: system
|
| 88 |
+
pass_filenames: false
|
| 89 |
+
types_or: [javascript, jsx, ts, tsx]
|
| 90 |
+
|
| 91 |
+
# swiftlint (same as CI)
|
| 92 |
+
- id: swiftlint
|
| 93 |
+
name: swiftlint
|
| 94 |
+
entry: swiftlint --config .swiftlint.yml
|
| 95 |
+
language: system
|
| 96 |
+
pass_filenames: false
|
| 97 |
+
types: [swift]
|
| 98 |
+
|
| 99 |
+
# swiftformat --lint (same as CI)
|
| 100 |
+
- id: swiftformat
|
| 101 |
+
name: swiftformat
|
| 102 |
+
entry: swiftformat --lint apps/macos/Sources --config .swiftformat
|
| 103 |
+
language: system
|
| 104 |
+
pass_filenames: false
|
| 105 |
+
types: [swift]
|
.prettierignore
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
src/canvas-host/a2ui/a2ui.bundle.js
|
.secrets.baseline
ADDED
|
@@ -0,0 +1,2191 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"version": "1.5.0",
|
| 3 |
+
"plugins_used": [
|
| 4 |
+
{
|
| 5 |
+
"name": "ArtifactoryDetector"
|
| 6 |
+
},
|
| 7 |
+
{
|
| 8 |
+
"name": "AWSKeyDetector"
|
| 9 |
+
},
|
| 10 |
+
{
|
| 11 |
+
"name": "AzureStorageKeyDetector"
|
| 12 |
+
},
|
| 13 |
+
{
|
| 14 |
+
"name": "Base64HighEntropyString",
|
| 15 |
+
"limit": 4.5
|
| 16 |
+
},
|
| 17 |
+
{
|
| 18 |
+
"name": "BasicAuthDetector"
|
| 19 |
+
},
|
| 20 |
+
{
|
| 21 |
+
"name": "CloudantDetector"
|
| 22 |
+
},
|
| 23 |
+
{
|
| 24 |
+
"name": "DiscordBotTokenDetector"
|
| 25 |
+
},
|
| 26 |
+
{
|
| 27 |
+
"name": "GitHubTokenDetector"
|
| 28 |
+
},
|
| 29 |
+
{
|
| 30 |
+
"name": "GitLabTokenDetector"
|
| 31 |
+
},
|
| 32 |
+
{
|
| 33 |
+
"name": "HexHighEntropyString",
|
| 34 |
+
"limit": 3.0
|
| 35 |
+
},
|
| 36 |
+
{
|
| 37 |
+
"name": "IbmCloudIamDetector"
|
| 38 |
+
},
|
| 39 |
+
{
|
| 40 |
+
"name": "IbmCosHmacDetector"
|
| 41 |
+
},
|
| 42 |
+
{
|
| 43 |
+
"name": "IPPublicDetector"
|
| 44 |
+
},
|
| 45 |
+
{
|
| 46 |
+
"name": "JwtTokenDetector"
|
| 47 |
+
},
|
| 48 |
+
{
|
| 49 |
+
"name": "KeywordDetector",
|
| 50 |
+
"keyword_exclude": ""
|
| 51 |
+
},
|
| 52 |
+
{
|
| 53 |
+
"name": "MailchimpDetector"
|
| 54 |
+
},
|
| 55 |
+
{
|
| 56 |
+
"name": "NpmDetector"
|
| 57 |
+
},
|
| 58 |
+
{
|
| 59 |
+
"name": "OpenAIDetector"
|
| 60 |
+
},
|
| 61 |
+
{
|
| 62 |
+
"name": "PrivateKeyDetector"
|
| 63 |
+
},
|
| 64 |
+
{
|
| 65 |
+
"name": "PypiTokenDetector"
|
| 66 |
+
},
|
| 67 |
+
{
|
| 68 |
+
"name": "SendGridDetector"
|
| 69 |
+
},
|
| 70 |
+
{
|
| 71 |
+
"name": "SlackDetector"
|
| 72 |
+
},
|
| 73 |
+
{
|
| 74 |
+
"name": "SoftlayerDetector"
|
| 75 |
+
},
|
| 76 |
+
{
|
| 77 |
+
"name": "SquareOAuthDetector"
|
| 78 |
+
},
|
| 79 |
+
{
|
| 80 |
+
"name": "StripeDetector"
|
| 81 |
+
},
|
| 82 |
+
{
|
| 83 |
+
"name": "TelegramBotTokenDetector"
|
| 84 |
+
},
|
| 85 |
+
{
|
| 86 |
+
"name": "TwilioKeyDetector"
|
| 87 |
+
}
|
| 88 |
+
],
|
| 89 |
+
"filters_used": [
|
| 90 |
+
{
|
| 91 |
+
"path": "detect_secrets.filters.allowlist.is_line_allowlisted"
|
| 92 |
+
},
|
| 93 |
+
{
|
| 94 |
+
"path": "detect_secrets.filters.common.is_baseline_file",
|
| 95 |
+
"filename": ".secrets.baseline"
|
| 96 |
+
},
|
| 97 |
+
{
|
| 98 |
+
"path": "detect_secrets.filters.common.is_ignored_due_to_verification_policies",
|
| 99 |
+
"min_level": 2
|
| 100 |
+
},
|
| 101 |
+
{
|
| 102 |
+
"path": "detect_secrets.filters.heuristic.is_indirect_reference"
|
| 103 |
+
},
|
| 104 |
+
{
|
| 105 |
+
"path": "detect_secrets.filters.heuristic.is_likely_id_string"
|
| 106 |
+
},
|
| 107 |
+
{
|
| 108 |
+
"path": "detect_secrets.filters.heuristic.is_lock_file"
|
| 109 |
+
},
|
| 110 |
+
{
|
| 111 |
+
"path": "detect_secrets.filters.heuristic.is_not_alphanumeric_string"
|
| 112 |
+
},
|
| 113 |
+
{
|
| 114 |
+
"path": "detect_secrets.filters.heuristic.is_potential_uuid"
|
| 115 |
+
},
|
| 116 |
+
{
|
| 117 |
+
"path": "detect_secrets.filters.heuristic.is_prefixed_with_dollar_sign"
|
| 118 |
+
},
|
| 119 |
+
{
|
| 120 |
+
"path": "detect_secrets.filters.heuristic.is_sequential_string"
|
| 121 |
+
},
|
| 122 |
+
{
|
| 123 |
+
"path": "detect_secrets.filters.heuristic.is_swagger_file"
|
| 124 |
+
},
|
| 125 |
+
{
|
| 126 |
+
"path": "detect_secrets.filters.heuristic.is_templated_secret"
|
| 127 |
+
},
|
| 128 |
+
{
|
| 129 |
+
"path": "detect_secrets.filters.regex.should_exclude_file",
|
| 130 |
+
"pattern": [
|
| 131 |
+
"(^|/)pnpm-lock\\.yaml$"
|
| 132 |
+
]
|
| 133 |
+
},
|
| 134 |
+
{
|
| 135 |
+
"path": "detect_secrets.filters.regex.should_exclude_line",
|
| 136 |
+
"pattern": [
|
| 137 |
+
"key_content\\.include\\?\\(\"BEGIN PRIVATE KEY\"\\)",
|
| 138 |
+
"case \\.apiKeyEnv: \"API key \\(env var\\)\"",
|
| 139 |
+
"case apikey = \"apiKey\"",
|
| 140 |
+
"\"gateway\\.remote\\.password\"",
|
| 141 |
+
"\"gateway\\.auth\\.password\"",
|
| 142 |
+
"\"talk\\.apiKey\"",
|
| 143 |
+
"=== \"string\"",
|
| 144 |
+
"typeof remote\\?\\.password === \"string\""
|
| 145 |
+
]
|
| 146 |
+
}
|
| 147 |
+
],
|
| 148 |
+
"results": {
|
| 149 |
+
".env.example": [
|
| 150 |
+
{
|
| 151 |
+
"type": "Twilio API Key",
|
| 152 |
+
"filename": ".env.example",
|
| 153 |
+
"hashed_secret": "3c7206eff845bc69cf12d904d0f95f9aec15535e",
|
| 154 |
+
"is_verified": false,
|
| 155 |
+
"line_number": 2
|
| 156 |
+
}
|
| 157 |
+
],
|
| 158 |
+
"appcast.xml": [
|
| 159 |
+
{
|
| 160 |
+
"type": "Base64 High Entropy String",
|
| 161 |
+
"filename": "appcast.xml",
|
| 162 |
+
"hashed_secret": "4e5f0a148d9ef42afeb73b1c77643e2ef2dee0b9",
|
| 163 |
+
"is_verified": false,
|
| 164 |
+
"line_number": 90
|
| 165 |
+
},
|
| 166 |
+
{
|
| 167 |
+
"type": "Base64 High Entropy String",
|
| 168 |
+
"filename": "appcast.xml",
|
| 169 |
+
"hashed_secret": "f1ccdaf78c308ec2cf608818da13f5f1e4809ed1",
|
| 170 |
+
"is_verified": false,
|
| 171 |
+
"line_number": 138
|
| 172 |
+
},
|
| 173 |
+
{
|
| 174 |
+
"type": "Base64 High Entropy String",
|
| 175 |
+
"filename": "appcast.xml",
|
| 176 |
+
"hashed_secret": "2691dc9c9ded92ba62a2d8ee589e2d78e2aa0479",
|
| 177 |
+
"is_verified": false,
|
| 178 |
+
"line_number": 212
|
| 179 |
+
}
|
| 180 |
+
],
|
| 181 |
+
"apps/macos/Tests/ClawdbotIPCTests/AnthropicAuthResolverTests.swift": [
|
| 182 |
+
{
|
| 183 |
+
"type": "Secret Keyword",
|
| 184 |
+
"filename": "apps/macos/Tests/ClawdbotIPCTests/AnthropicAuthResolverTests.swift",
|
| 185 |
+
"hashed_secret": "e761624445731fcb8b15da94343c6b92e507d190",
|
| 186 |
+
"is_verified": false,
|
| 187 |
+
"line_number": 26
|
| 188 |
+
},
|
| 189 |
+
{
|
| 190 |
+
"type": "Secret Keyword",
|
| 191 |
+
"filename": "apps/macos/Tests/ClawdbotIPCTests/AnthropicAuthResolverTests.swift",
|
| 192 |
+
"hashed_secret": "a23c8630c8a5fbaa21f095e0269c135c20d21689",
|
| 193 |
+
"is_verified": false,
|
| 194 |
+
"line_number": 42
|
| 195 |
+
}
|
| 196 |
+
],
|
| 197 |
+
"apps/macos/Tests/ClawdbotIPCTests/GatewayEndpointStoreTests.swift": [
|
| 198 |
+
{
|
| 199 |
+
"type": "Secret Keyword",
|
| 200 |
+
"filename": "apps/macos/Tests/ClawdbotIPCTests/GatewayEndpointStoreTests.swift",
|
| 201 |
+
"hashed_secret": "19dad5cecb110281417d1db56b60e1b006d55bb4",
|
| 202 |
+
"is_verified": false,
|
| 203 |
+
"line_number": 61
|
| 204 |
+
}
|
| 205 |
+
],
|
| 206 |
+
"apps/macos/Tests/ClawdbotIPCTests/GatewayLaunchAgentManagerTests.swift": [
|
| 207 |
+
{
|
| 208 |
+
"type": "Secret Keyword",
|
| 209 |
+
"filename": "apps/macos/Tests/ClawdbotIPCTests/GatewayLaunchAgentManagerTests.swift",
|
| 210 |
+
"hashed_secret": "1a91d62f7ca67399625a4368a6ab5d4a3baa6073",
|
| 211 |
+
"is_verified": false,
|
| 212 |
+
"line_number": 13
|
| 213 |
+
}
|
| 214 |
+
],
|
| 215 |
+
"apps/macos/Tests/ClawdbotIPCTests/TailscaleIntegrationSectionTests.swift": [
|
| 216 |
+
{
|
| 217 |
+
"type": "Secret Keyword",
|
| 218 |
+
"filename": "apps/macos/Tests/ClawdbotIPCTests/TailscaleIntegrationSectionTests.swift",
|
| 219 |
+
"hashed_secret": "e5e9fa1ba31ecd1ae84f75caaa474f3a663f05f4",
|
| 220 |
+
"is_verified": false,
|
| 221 |
+
"line_number": 27
|
| 222 |
+
}
|
| 223 |
+
],
|
| 224 |
+
"apps/shared/ClawdbotKit/Sources/ClawdbotKit/GatewayChannel.swift": [
|
| 225 |
+
{
|
| 226 |
+
"type": "Secret Keyword",
|
| 227 |
+
"filename": "apps/shared/ClawdbotKit/Sources/ClawdbotKit/GatewayChannel.swift",
|
| 228 |
+
"hashed_secret": "5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8",
|
| 229 |
+
"is_verified": false,
|
| 230 |
+
"line_number": 100
|
| 231 |
+
}
|
| 232 |
+
],
|
| 233 |
+
"docs/brave-search.md": [
|
| 234 |
+
{
|
| 235 |
+
"type": "Secret Keyword",
|
| 236 |
+
"filename": "docs/brave-search.md",
|
| 237 |
+
"hashed_secret": "491d458f895b9213facb2ee9375b1b044eaea3ac",
|
| 238 |
+
"is_verified": false,
|
| 239 |
+
"line_number": 26
|
| 240 |
+
}
|
| 241 |
+
],
|
| 242 |
+
"docs/channels/bluebubbles.md": [
|
| 243 |
+
{
|
| 244 |
+
"type": "Secret Keyword",
|
| 245 |
+
"filename": "docs/channels/bluebubbles.md",
|
| 246 |
+
"hashed_secret": "555da20df20d4172e00f1b73d7c3943802055270",
|
| 247 |
+
"is_verified": false,
|
| 248 |
+
"line_number": 32
|
| 249 |
+
}
|
| 250 |
+
],
|
| 251 |
+
"docs/channels/matrix.md": [
|
| 252 |
+
{
|
| 253 |
+
"type": "Secret Keyword",
|
| 254 |
+
"filename": "docs/channels/matrix.md",
|
| 255 |
+
"hashed_secret": "45d676e7c6ab44cf4b8fa366ef2d8fccd3e6d6e6",
|
| 256 |
+
"is_verified": false,
|
| 257 |
+
"line_number": 58
|
| 258 |
+
}
|
| 259 |
+
],
|
| 260 |
+
"docs/channels/nextcloud-talk.md": [
|
| 261 |
+
{
|
| 262 |
+
"type": "Secret Keyword",
|
| 263 |
+
"filename": "docs/channels/nextcloud-talk.md",
|
| 264 |
+
"hashed_secret": "76ed0a056aa77060de25754586440cff390791d0",
|
| 265 |
+
"is_verified": false,
|
| 266 |
+
"line_number": 47
|
| 267 |
+
}
|
| 268 |
+
],
|
| 269 |
+
"docs/channels/nostr.md": [
|
| 270 |
+
{
|
| 271 |
+
"type": "Secret Keyword",
|
| 272 |
+
"filename": "docs/channels/nostr.md",
|
| 273 |
+
"hashed_secret": "edeb23e25a619c434d22bb7f1c3ca4841166b4e8",
|
| 274 |
+
"is_verified": false,
|
| 275 |
+
"line_number": 65
|
| 276 |
+
}
|
| 277 |
+
],
|
| 278 |
+
"docs/channels/slack.md": [
|
| 279 |
+
{
|
| 280 |
+
"type": "Secret Keyword",
|
| 281 |
+
"filename": "docs/channels/slack.md",
|
| 282 |
+
"hashed_secret": "3f4800fb7c1fb79a9a48bfd562d90bc6b2e2b718",
|
| 283 |
+
"is_verified": false,
|
| 284 |
+
"line_number": 141
|
| 285 |
+
}
|
| 286 |
+
],
|
| 287 |
+
"docs/concepts/memory.md": [
|
| 288 |
+
{
|
| 289 |
+
"type": "Secret Keyword",
|
| 290 |
+
"filename": "docs/concepts/memory.md",
|
| 291 |
+
"hashed_secret": "39d711243bfcee9fec8299b204e1aa9c3430fa12",
|
| 292 |
+
"is_verified": false,
|
| 293 |
+
"line_number": 108
|
| 294 |
+
},
|
| 295 |
+
{
|
| 296 |
+
"type": "Secret Keyword",
|
| 297 |
+
"filename": "docs/concepts/memory.md",
|
| 298 |
+
"hashed_secret": "1a8abbf465c52363ab4c9c6ad945b8e857cbea55",
|
| 299 |
+
"is_verified": false,
|
| 300 |
+
"line_number": 131
|
| 301 |
+
},
|
| 302 |
+
{
|
| 303 |
+
"type": "Secret Keyword",
|
| 304 |
+
"filename": "docs/concepts/memory.md",
|
| 305 |
+
"hashed_secret": "b9f640d6095b9f6b5a65983f7b76dbbb254e0044",
|
| 306 |
+
"is_verified": false,
|
| 307 |
+
"line_number": 373
|
| 308 |
+
}
|
| 309 |
+
],
|
| 310 |
+
"docs/concepts/model-providers.md": [
|
| 311 |
+
{
|
| 312 |
+
"type": "Secret Keyword",
|
| 313 |
+
"filename": "docs/concepts/model-providers.md",
|
| 314 |
+
"hashed_secret": "ec3810e10fb78db55ce38b9c18d1c3eb1db739e0",
|
| 315 |
+
"is_verified": false,
|
| 316 |
+
"line_number": 168
|
| 317 |
+
},
|
| 318 |
+
{
|
| 319 |
+
"type": "Secret Keyword",
|
| 320 |
+
"filename": "docs/concepts/model-providers.md",
|
| 321 |
+
"hashed_secret": "ef83ad68b9b66e008727b7c417c6a8f618b5177e",
|
| 322 |
+
"is_verified": false,
|
| 323 |
+
"line_number": 255
|
| 324 |
+
}
|
| 325 |
+
],
|
| 326 |
+
"docs/environment.md": [
|
| 327 |
+
{
|
| 328 |
+
"type": "Secret Keyword",
|
| 329 |
+
"filename": "docs/environment.md",
|
| 330 |
+
"hashed_secret": "a219d7693c25cd2d93313512e200ff3eb374d281",
|
| 331 |
+
"is_verified": false,
|
| 332 |
+
"line_number": 29
|
| 333 |
+
},
|
| 334 |
+
{
|
| 335 |
+
"type": "Secret Keyword",
|
| 336 |
+
"filename": "docs/environment.md",
|
| 337 |
+
"hashed_secret": "b6f56e5e92078ed7c078c46fbfeedcbe5719bc25",
|
| 338 |
+
"is_verified": false,
|
| 339 |
+
"line_number": 31
|
| 340 |
+
}
|
| 341 |
+
],
|
| 342 |
+
"docs/gateway/configuration-examples.md": [
|
| 343 |
+
{
|
| 344 |
+
"type": "Secret Keyword",
|
| 345 |
+
"filename": "docs/gateway/configuration-examples.md",
|
| 346 |
+
"hashed_secret": "a219d7693c25cd2d93313512e200ff3eb374d281",
|
| 347 |
+
"is_verified": false,
|
| 348 |
+
"line_number": 53
|
| 349 |
+
},
|
| 350 |
+
{
|
| 351 |
+
"type": "Secret Keyword",
|
| 352 |
+
"filename": "docs/gateway/configuration-examples.md",
|
| 353 |
+
"hashed_secret": "b6f56e5e92078ed7c078c46fbfeedcbe5719bc25",
|
| 354 |
+
"is_verified": false,
|
| 355 |
+
"line_number": 55
|
| 356 |
+
},
|
| 357 |
+
{
|
| 358 |
+
"type": "Secret Keyword",
|
| 359 |
+
"filename": "docs/gateway/configuration-examples.md",
|
| 360 |
+
"hashed_secret": "22af290a1a3d5e941193a41a3d3a9e4ca8da5e27",
|
| 361 |
+
"is_verified": false,
|
| 362 |
+
"line_number": 319
|
| 363 |
+
},
|
| 364 |
+
{
|
| 365 |
+
"type": "Secret Keyword",
|
| 366 |
+
"filename": "docs/gateway/configuration-examples.md",
|
| 367 |
+
"hashed_secret": "c1e6ee547fd492df1441ac492e8bb294974712bd",
|
| 368 |
+
"is_verified": false,
|
| 369 |
+
"line_number": 414
|
| 370 |
+
},
|
| 371 |
+
{
|
| 372 |
+
"type": "Secret Keyword",
|
| 373 |
+
"filename": "docs/gateway/configuration-examples.md",
|
| 374 |
+
"hashed_secret": "16c249e04e2be318050cb883c40137361c0c7209",
|
| 375 |
+
"is_verified": false,
|
| 376 |
+
"line_number": 548
|
| 377 |
+
}
|
| 378 |
+
],
|
| 379 |
+
"docs/gateway/configuration.md": [
|
| 380 |
+
{
|
| 381 |
+
"type": "Secret Keyword",
|
| 382 |
+
"filename": "docs/gateway/configuration.md",
|
| 383 |
+
"hashed_secret": "a219d7693c25cd2d93313512e200ff3eb374d281",
|
| 384 |
+
"is_verified": false,
|
| 385 |
+
"line_number": 272
|
| 386 |
+
},
|
| 387 |
+
{
|
| 388 |
+
"type": "Secret Keyword",
|
| 389 |
+
"filename": "docs/gateway/configuration.md",
|
| 390 |
+
"hashed_secret": "b6f56e5e92078ed7c078c46fbfeedcbe5719bc25",
|
| 391 |
+
"is_verified": false,
|
| 392 |
+
"line_number": 274
|
| 393 |
+
},
|
| 394 |
+
{
|
| 395 |
+
"type": "Secret Keyword",
|
| 396 |
+
"filename": "docs/gateway/configuration.md",
|
| 397 |
+
"hashed_secret": "e5e9fa1ba31ecd1ae84f75caaa474f3a663f05f4",
|
| 398 |
+
"is_verified": false,
|
| 399 |
+
"line_number": 1029
|
| 400 |
+
},
|
| 401 |
+
{
|
| 402 |
+
"type": "Secret Keyword",
|
| 403 |
+
"filename": "docs/gateway/configuration.md",
|
| 404 |
+
"hashed_secret": "1188d5a8ed7edcff5144a9472af960243eacf12e",
|
| 405 |
+
"is_verified": false,
|
| 406 |
+
"line_number": 1470
|
| 407 |
+
},
|
| 408 |
+
{
|
| 409 |
+
"type": "Secret Keyword",
|
| 410 |
+
"filename": "docs/gateway/configuration.md",
|
| 411 |
+
"hashed_secret": "bde4db9b4c3be4049adc3b9a69851d7c35119770",
|
| 412 |
+
"is_verified": false,
|
| 413 |
+
"line_number": 1486
|
| 414 |
+
},
|
| 415 |
+
{
|
| 416 |
+
"type": "Secret Keyword",
|
| 417 |
+
"filename": "docs/gateway/configuration.md",
|
| 418 |
+
"hashed_secret": "22af290a1a3d5e941193a41a3d3a9e4ca8da5e27",
|
| 419 |
+
"is_verified": false,
|
| 420 |
+
"line_number": 2268
|
| 421 |
+
},
|
| 422 |
+
{
|
| 423 |
+
"type": "Secret Keyword",
|
| 424 |
+
"filename": "docs/gateway/configuration.md",
|
| 425 |
+
"hashed_secret": "ec3810e10fb78db55ce38b9c18d1c3eb1db739e0",
|
| 426 |
+
"is_verified": false,
|
| 427 |
+
"line_number": 2344
|
| 428 |
+
},
|
| 429 |
+
{
|
| 430 |
+
"type": "Secret Keyword",
|
| 431 |
+
"filename": "docs/gateway/configuration.md",
|
| 432 |
+
"hashed_secret": "c1e6ee547fd492df1441ac492e8bb294974712bd",
|
| 433 |
+
"is_verified": false,
|
| 434 |
+
"line_number": 2658
|
| 435 |
+
},
|
| 436 |
+
{
|
| 437 |
+
"type": "Secret Keyword",
|
| 438 |
+
"filename": "docs/gateway/configuration.md",
|
| 439 |
+
"hashed_secret": "45d676e7c6ab44cf4b8fa366ef2d8fccd3e6d6e6",
|
| 440 |
+
"is_verified": false,
|
| 441 |
+
"line_number": 2844
|
| 442 |
+
}
|
| 443 |
+
],
|
| 444 |
+
"docs/gateway/local-models.md": [
|
| 445 |
+
{
|
| 446 |
+
"type": "Secret Keyword",
|
| 447 |
+
"filename": "docs/gateway/local-models.md",
|
| 448 |
+
"hashed_secret": "16c249e04e2be318050cb883c40137361c0c7209",
|
| 449 |
+
"is_verified": false,
|
| 450 |
+
"line_number": 32
|
| 451 |
+
},
|
| 452 |
+
{
|
| 453 |
+
"type": "Secret Keyword",
|
| 454 |
+
"filename": "docs/gateway/local-models.md",
|
| 455 |
+
"hashed_secret": "49fd535e63175a827aab3eff9ac58a9e82460ac9",
|
| 456 |
+
"is_verified": false,
|
| 457 |
+
"line_number": 121
|
| 458 |
+
}
|
| 459 |
+
],
|
| 460 |
+
"docs/gateway/tailscale.md": [
|
| 461 |
+
{
|
| 462 |
+
"type": "Secret Keyword",
|
| 463 |
+
"filename": "docs/gateway/tailscale.md",
|
| 464 |
+
"hashed_secret": "9cb0dc5383312aa15b9dc6745645bde18ff5ade9",
|
| 465 |
+
"is_verified": false,
|
| 466 |
+
"line_number": 75
|
| 467 |
+
}
|
| 468 |
+
],
|
| 469 |
+
"docs/help/faq.md": [
|
| 470 |
+
{
|
| 471 |
+
"type": "Secret Keyword",
|
| 472 |
+
"filename": "docs/help/faq.md",
|
| 473 |
+
"hashed_secret": "491d458f895b9213facb2ee9375b1b044eaea3ac",
|
| 474 |
+
"is_verified": false,
|
| 475 |
+
"line_number": 925
|
| 476 |
+
},
|
| 477 |
+
{
|
| 478 |
+
"type": "Secret Keyword",
|
| 479 |
+
"filename": "docs/help/faq.md",
|
| 480 |
+
"hashed_secret": "a219d7693c25cd2d93313512e200ff3eb374d281",
|
| 481 |
+
"is_verified": false,
|
| 482 |
+
"line_number": 1113
|
| 483 |
+
},
|
| 484 |
+
{
|
| 485 |
+
"type": "Secret Keyword",
|
| 486 |
+
"filename": "docs/help/faq.md",
|
| 487 |
+
"hashed_secret": "b6f56e5e92078ed7c078c46fbfeedcbe5719bc25",
|
| 488 |
+
"is_verified": false,
|
| 489 |
+
"line_number": 1114
|
| 490 |
+
},
|
| 491 |
+
{
|
| 492 |
+
"type": "Secret Keyword",
|
| 493 |
+
"filename": "docs/help/faq.md",
|
| 494 |
+
"hashed_secret": "ec3810e10fb78db55ce38b9c18d1c3eb1db739e0",
|
| 495 |
+
"is_verified": false,
|
| 496 |
+
"line_number": 1439
|
| 497 |
+
},
|
| 498 |
+
{
|
| 499 |
+
"type": "Secret Keyword",
|
| 500 |
+
"filename": "docs/help/faq.md",
|
| 501 |
+
"hashed_secret": "45d676e7c6ab44cf4b8fa366ef2d8fccd3e6d6e6",
|
| 502 |
+
"is_verified": false,
|
| 503 |
+
"line_number": 1715
|
| 504 |
+
}
|
| 505 |
+
],
|
| 506 |
+
"docs/nodes/talk.md": [
|
| 507 |
+
{
|
| 508 |
+
"type": "Secret Keyword",
|
| 509 |
+
"filename": "docs/nodes/talk.md",
|
| 510 |
+
"hashed_secret": "1188d5a8ed7edcff5144a9472af960243eacf12e",
|
| 511 |
+
"is_verified": false,
|
| 512 |
+
"line_number": 50
|
| 513 |
+
}
|
| 514 |
+
],
|
| 515 |
+
"docs/perplexity.md": [
|
| 516 |
+
{
|
| 517 |
+
"type": "Secret Keyword",
|
| 518 |
+
"filename": "docs/perplexity.md",
|
| 519 |
+
"hashed_secret": "6b26c117c66a0c030e239eef595c1e18865132a8",
|
| 520 |
+
"is_verified": false,
|
| 521 |
+
"line_number": 35
|
| 522 |
+
}
|
| 523 |
+
],
|
| 524 |
+
"docs/providers/anthropic.md": [
|
| 525 |
+
{
|
| 526 |
+
"type": "Secret Keyword",
|
| 527 |
+
"filename": "docs/providers/anthropic.md",
|
| 528 |
+
"hashed_secret": "c7a8c334eef5d1749fface7d42c66f9ae5e8cf36",
|
| 529 |
+
"is_verified": false,
|
| 530 |
+
"line_number": 32
|
| 531 |
+
}
|
| 532 |
+
],
|
| 533 |
+
"docs/providers/glm.md": [
|
| 534 |
+
{
|
| 535 |
+
"type": "Secret Keyword",
|
| 536 |
+
"filename": "docs/providers/glm.md",
|
| 537 |
+
"hashed_secret": "ec3810e10fb78db55ce38b9c18d1c3eb1db739e0",
|
| 538 |
+
"is_verified": false,
|
| 539 |
+
"line_number": 22
|
| 540 |
+
}
|
| 541 |
+
],
|
| 542 |
+
"docs/providers/minimax.md": [
|
| 543 |
+
{
|
| 544 |
+
"type": "Secret Keyword",
|
| 545 |
+
"filename": "docs/providers/minimax.md",
|
| 546 |
+
"hashed_secret": "ec3810e10fb78db55ce38b9c18d1c3eb1db739e0",
|
| 547 |
+
"is_verified": false,
|
| 548 |
+
"line_number": 49
|
| 549 |
+
},
|
| 550 |
+
{
|
| 551 |
+
"type": "Secret Keyword",
|
| 552 |
+
"filename": "docs/providers/minimax.md",
|
| 553 |
+
"hashed_secret": "16c249e04e2be318050cb883c40137361c0c7209",
|
| 554 |
+
"is_verified": false,
|
| 555 |
+
"line_number": 118
|
| 556 |
+
}
|
| 557 |
+
],
|
| 558 |
+
"docs/providers/moonshot.md": [
|
| 559 |
+
{
|
| 560 |
+
"type": "Secret Keyword",
|
| 561 |
+
"filename": "docs/providers/moonshot.md",
|
| 562 |
+
"hashed_secret": "ec3810e10fb78db55ce38b9c18d1c3eb1db739e0",
|
| 563 |
+
"is_verified": false,
|
| 564 |
+
"line_number": 39
|
| 565 |
+
}
|
| 566 |
+
],
|
| 567 |
+
"docs/providers/openai.md": [
|
| 568 |
+
{
|
| 569 |
+
"type": "Secret Keyword",
|
| 570 |
+
"filename": "docs/providers/openai.md",
|
| 571 |
+
"hashed_secret": "ec3810e10fb78db55ce38b9c18d1c3eb1db739e0",
|
| 572 |
+
"is_verified": false,
|
| 573 |
+
"line_number": 31
|
| 574 |
+
}
|
| 575 |
+
],
|
| 576 |
+
"docs/providers/opencode.md": [
|
| 577 |
+
{
|
| 578 |
+
"type": "Secret Keyword",
|
| 579 |
+
"filename": "docs/providers/opencode.md",
|
| 580 |
+
"hashed_secret": "ec3810e10fb78db55ce38b9c18d1c3eb1db739e0",
|
| 581 |
+
"is_verified": false,
|
| 582 |
+
"line_number": 25
|
| 583 |
+
}
|
| 584 |
+
],
|
| 585 |
+
"docs/providers/openrouter.md": [
|
| 586 |
+
{
|
| 587 |
+
"type": "Secret Keyword",
|
| 588 |
+
"filename": "docs/providers/openrouter.md",
|
| 589 |
+
"hashed_secret": "a219d7693c25cd2d93313512e200ff3eb374d281",
|
| 590 |
+
"is_verified": false,
|
| 591 |
+
"line_number": 22
|
| 592 |
+
}
|
| 593 |
+
],
|
| 594 |
+
"docs/providers/synthetic.md": [
|
| 595 |
+
{
|
| 596 |
+
"type": "Secret Keyword",
|
| 597 |
+
"filename": "docs/providers/synthetic.md",
|
| 598 |
+
"hashed_secret": "ec3810e10fb78db55ce38b9c18d1c3eb1db739e0",
|
| 599 |
+
"is_verified": false,
|
| 600 |
+
"line_number": 31
|
| 601 |
+
}
|
| 602 |
+
],
|
| 603 |
+
"docs/providers/zai.md": [
|
| 604 |
+
{
|
| 605 |
+
"type": "Secret Keyword",
|
| 606 |
+
"filename": "docs/providers/zai.md",
|
| 607 |
+
"hashed_secret": "ec3810e10fb78db55ce38b9c18d1c3eb1db739e0",
|
| 608 |
+
"is_verified": false,
|
| 609 |
+
"line_number": 25
|
| 610 |
+
}
|
| 611 |
+
],
|
| 612 |
+
"docs/tools/browser.md": [
|
| 613 |
+
{
|
| 614 |
+
"type": "Basic Auth Credentials",
|
| 615 |
+
"filename": "docs/tools/browser.md",
|
| 616 |
+
"hashed_secret": "9d4e1e23bd5b727046a9e3b4b7db57bd8d6ee684",
|
| 617 |
+
"is_verified": false,
|
| 618 |
+
"line_number": 163
|
| 619 |
+
}
|
| 620 |
+
],
|
| 621 |
+
"docs/tools/firecrawl.md": [
|
| 622 |
+
{
|
| 623 |
+
"type": "Secret Keyword",
|
| 624 |
+
"filename": "docs/tools/firecrawl.md",
|
| 625 |
+
"hashed_secret": "674397e2c0c2faaa85961c708d2a96a7cc7af217",
|
| 626 |
+
"is_verified": false,
|
| 627 |
+
"line_number": 28
|
| 628 |
+
}
|
| 629 |
+
],
|
| 630 |
+
"docs/tools/skills-config.md": [
|
| 631 |
+
{
|
| 632 |
+
"type": "Secret Keyword",
|
| 633 |
+
"filename": "docs/tools/skills-config.md",
|
| 634 |
+
"hashed_secret": "c1e6ee547fd492df1441ac492e8bb294974712bd",
|
| 635 |
+
"is_verified": false,
|
| 636 |
+
"line_number": 30
|
| 637 |
+
}
|
| 638 |
+
],
|
| 639 |
+
"docs/tools/skills.md": [
|
| 640 |
+
{
|
| 641 |
+
"type": "Secret Keyword",
|
| 642 |
+
"filename": "docs/tools/skills.md",
|
| 643 |
+
"hashed_secret": "c1e6ee547fd492df1441ac492e8bb294974712bd",
|
| 644 |
+
"is_verified": false,
|
| 645 |
+
"line_number": 160
|
| 646 |
+
}
|
| 647 |
+
],
|
| 648 |
+
"docs/tools/web.md": [
|
| 649 |
+
{
|
| 650 |
+
"type": "Secret Keyword",
|
| 651 |
+
"filename": "docs/tools/web.md",
|
| 652 |
+
"hashed_secret": "6b26c117c66a0c030e239eef595c1e18865132a8",
|
| 653 |
+
"is_verified": false,
|
| 654 |
+
"line_number": 61
|
| 655 |
+
},
|
| 656 |
+
{
|
| 657 |
+
"type": "Secret Keyword",
|
| 658 |
+
"filename": "docs/tools/web.md",
|
| 659 |
+
"hashed_secret": "96c682c88ed551f22fe76d206c2dfb7df9221ad9",
|
| 660 |
+
"is_verified": false,
|
| 661 |
+
"line_number": 112
|
| 662 |
+
},
|
| 663 |
+
{
|
| 664 |
+
"type": "Secret Keyword",
|
| 665 |
+
"filename": "docs/tools/web.md",
|
| 666 |
+
"hashed_secret": "491d458f895b9213facb2ee9375b1b044eaea3ac",
|
| 667 |
+
"is_verified": false,
|
| 668 |
+
"line_number": 160
|
| 669 |
+
},
|
| 670 |
+
{
|
| 671 |
+
"type": "Secret Keyword",
|
| 672 |
+
"filename": "docs/tools/web.md",
|
| 673 |
+
"hashed_secret": "674397e2c0c2faaa85961c708d2a96a7cc7af217",
|
| 674 |
+
"is_verified": false,
|
| 675 |
+
"line_number": 223
|
| 676 |
+
}
|
| 677 |
+
],
|
| 678 |
+
"docs/tts.md": [
|
| 679 |
+
{
|
| 680 |
+
"type": "Secret Keyword",
|
| 681 |
+
"filename": "docs/tts.md",
|
| 682 |
+
"hashed_secret": "bde4db9b4c3be4049adc3b9a69851d7c35119770",
|
| 683 |
+
"is_verified": false,
|
| 684 |
+
"line_number": 72
|
| 685 |
+
},
|
| 686 |
+
{
|
| 687 |
+
"type": "Secret Keyword",
|
| 688 |
+
"filename": "docs/tts.md",
|
| 689 |
+
"hashed_secret": "1188d5a8ed7edcff5144a9472af960243eacf12e",
|
| 690 |
+
"is_verified": false,
|
| 691 |
+
"line_number": 77
|
| 692 |
+
}
|
| 693 |
+
],
|
| 694 |
+
"extensions/bluebubbles/src/actions.test.ts": [
|
| 695 |
+
{
|
| 696 |
+
"type": "Secret Keyword",
|
| 697 |
+
"filename": "extensions/bluebubbles/src/actions.test.ts",
|
| 698 |
+
"hashed_secret": "789cbe0407840b1c2041cb33452ff60f19bf58cc",
|
| 699 |
+
"is_verified": false,
|
| 700 |
+
"line_number": 73
|
| 701 |
+
}
|
| 702 |
+
],
|
| 703 |
+
"extensions/bluebubbles/src/attachments.test.ts": [
|
| 704 |
+
{
|
| 705 |
+
"type": "Secret Keyword",
|
| 706 |
+
"filename": "extensions/bluebubbles/src/attachments.test.ts",
|
| 707 |
+
"hashed_secret": "789cbe0407840b1c2041cb33452ff60f19bf58cc",
|
| 708 |
+
"is_verified": false,
|
| 709 |
+
"line_number": 35
|
| 710 |
+
},
|
| 711 |
+
{
|
| 712 |
+
"type": "Secret Keyword",
|
| 713 |
+
"filename": "extensions/bluebubbles/src/attachments.test.ts",
|
| 714 |
+
"hashed_secret": "db1530e1ea43af094d3d75b8dbaf19a4a182a318",
|
| 715 |
+
"is_verified": false,
|
| 716 |
+
"line_number": 99
|
| 717 |
+
},
|
| 718 |
+
{
|
| 719 |
+
"type": "Secret Keyword",
|
| 720 |
+
"filename": "extensions/bluebubbles/src/attachments.test.ts",
|
| 721 |
+
"hashed_secret": "a94a8fe5ccb19ba61c4c0873d391e987982fbbd3",
|
| 722 |
+
"is_verified": false,
|
| 723 |
+
"line_number": 117
|
| 724 |
+
},
|
| 725 |
+
{
|
| 726 |
+
"type": "Secret Keyword",
|
| 727 |
+
"filename": "extensions/bluebubbles/src/attachments.test.ts",
|
| 728 |
+
"hashed_secret": "052f076c732648ab32d2fcde9fe255319bfa0c7b",
|
| 729 |
+
"is_verified": false,
|
| 730 |
+
"line_number": 229
|
| 731 |
+
}
|
| 732 |
+
],
|
| 733 |
+
"extensions/bluebubbles/src/chat.test.ts": [
|
| 734 |
+
{
|
| 735 |
+
"type": "Secret Keyword",
|
| 736 |
+
"filename": "extensions/bluebubbles/src/chat.test.ts",
|
| 737 |
+
"hashed_secret": "a94a8fe5ccb19ba61c4c0873d391e987982fbbd3",
|
| 738 |
+
"is_verified": false,
|
| 739 |
+
"line_number": 33
|
| 740 |
+
},
|
| 741 |
+
{
|
| 742 |
+
"type": "Secret Keyword",
|
| 743 |
+
"filename": "extensions/bluebubbles/src/chat.test.ts",
|
| 744 |
+
"hashed_secret": "789cbe0407840b1c2041cb33452ff60f19bf58cc",
|
| 745 |
+
"is_verified": false,
|
| 746 |
+
"line_number": 68
|
| 747 |
+
},
|
| 748 |
+
{
|
| 749 |
+
"type": "Secret Keyword",
|
| 750 |
+
"filename": "extensions/bluebubbles/src/chat.test.ts",
|
| 751 |
+
"hashed_secret": "5c5a15a8b0b3e154d77746945e563ba40100681b",
|
| 752 |
+
"is_verified": false,
|
| 753 |
+
"line_number": 85
|
| 754 |
+
},
|
| 755 |
+
{
|
| 756 |
+
"type": "Secret Keyword",
|
| 757 |
+
"filename": "extensions/bluebubbles/src/chat.test.ts",
|
| 758 |
+
"hashed_secret": "faacad0ce4ea1c19b46e128fd79679d37d3d331d",
|
| 759 |
+
"is_verified": false,
|
| 760 |
+
"line_number": 134
|
| 761 |
+
},
|
| 762 |
+
{
|
| 763 |
+
"type": "Secret Keyword",
|
| 764 |
+
"filename": "extensions/bluebubbles/src/chat.test.ts",
|
| 765 |
+
"hashed_secret": "4dcc26a1d99532846fedf1265df4f40f4e0005b8",
|
| 766 |
+
"is_verified": false,
|
| 767 |
+
"line_number": 219
|
| 768 |
+
},
|
| 769 |
+
{
|
| 770 |
+
"type": "Secret Keyword",
|
| 771 |
+
"filename": "extensions/bluebubbles/src/chat.test.ts",
|
| 772 |
+
"hashed_secret": "fd2a721f7be1ee3d691a011affcdb11d0ca365a8",
|
| 773 |
+
"is_verified": false,
|
| 774 |
+
"line_number": 282
|
| 775 |
+
}
|
| 776 |
+
],
|
| 777 |
+
"extensions/bluebubbles/src/monitor.test.ts": [
|
| 778 |
+
{
|
| 779 |
+
"type": "Secret Keyword",
|
| 780 |
+
"filename": "extensions/bluebubbles/src/monitor.test.ts",
|
| 781 |
+
"hashed_secret": "789cbe0407840b1c2041cb33452ff60f19bf58cc",
|
| 782 |
+
"is_verified": false,
|
| 783 |
+
"line_number": 187
|
| 784 |
+
},
|
| 785 |
+
{
|
| 786 |
+
"type": "Secret Keyword",
|
| 787 |
+
"filename": "extensions/bluebubbles/src/monitor.test.ts",
|
| 788 |
+
"hashed_secret": "1ae0af3fe72b3ba394f9fa95a6cffc090d726c23",
|
| 789 |
+
"is_verified": false,
|
| 790 |
+
"line_number": 394
|
| 791 |
+
}
|
| 792 |
+
],
|
| 793 |
+
"extensions/bluebubbles/src/reactions.test.ts": [
|
| 794 |
+
{
|
| 795 |
+
"type": "Secret Keyword",
|
| 796 |
+
"filename": "extensions/bluebubbles/src/reactions.test.ts",
|
| 797 |
+
"hashed_secret": "a94a8fe5ccb19ba61c4c0873d391e987982fbbd3",
|
| 798 |
+
"is_verified": false,
|
| 799 |
+
"line_number": 38
|
| 800 |
+
},
|
| 801 |
+
{
|
| 802 |
+
"type": "Secret Keyword",
|
| 803 |
+
"filename": "extensions/bluebubbles/src/reactions.test.ts",
|
| 804 |
+
"hashed_secret": "789cbe0407840b1c2041cb33452ff60f19bf58cc",
|
| 805 |
+
"is_verified": false,
|
| 806 |
+
"line_number": 179
|
| 807 |
+
},
|
| 808 |
+
{
|
| 809 |
+
"type": "Secret Keyword",
|
| 810 |
+
"filename": "extensions/bluebubbles/src/reactions.test.ts",
|
| 811 |
+
"hashed_secret": "a4a05c9a6449eb9d6cdac81dd7edc49230e327e6",
|
| 812 |
+
"is_verified": false,
|
| 813 |
+
"line_number": 210
|
| 814 |
+
},
|
| 815 |
+
{
|
| 816 |
+
"type": "Secret Keyword",
|
| 817 |
+
"filename": "extensions/bluebubbles/src/reactions.test.ts",
|
| 818 |
+
"hashed_secret": "a2833da9f0a16f09994754d0a31749cecf8c8c77",
|
| 819 |
+
"is_verified": false,
|
| 820 |
+
"line_number": 316
|
| 821 |
+
}
|
| 822 |
+
],
|
| 823 |
+
"extensions/bluebubbles/src/send.test.ts": [
|
| 824 |
+
{
|
| 825 |
+
"type": "Secret Keyword",
|
| 826 |
+
"filename": "extensions/bluebubbles/src/send.test.ts",
|
| 827 |
+
"hashed_secret": "a94a8fe5ccb19ba61c4c0873d391e987982fbbd3",
|
| 828 |
+
"is_verified": false,
|
| 829 |
+
"line_number": 38
|
| 830 |
+
},
|
| 831 |
+
{
|
| 832 |
+
"type": "Secret Keyword",
|
| 833 |
+
"filename": "extensions/bluebubbles/src/send.test.ts",
|
| 834 |
+
"hashed_secret": "faacad0ce4ea1c19b46e128fd79679d37d3d331d",
|
| 835 |
+
"is_verified": false,
|
| 836 |
+
"line_number": 675
|
| 837 |
+
}
|
| 838 |
+
],
|
| 839 |
+
"extensions/bluebubbles/src/targets.test.ts": [
|
| 840 |
+
{
|
| 841 |
+
"type": "Hex High Entropy String",
|
| 842 |
+
"filename": "extensions/bluebubbles/src/targets.test.ts",
|
| 843 |
+
"hashed_secret": "a3af2fb0c1e2a30bb038049e1e4b401593af6225",
|
| 844 |
+
"is_verified": false,
|
| 845 |
+
"line_number": 62
|
| 846 |
+
}
|
| 847 |
+
],
|
| 848 |
+
"extensions/bluebubbles/src/targets.ts": [
|
| 849 |
+
{
|
| 850 |
+
"type": "Hex High Entropy String",
|
| 851 |
+
"filename": "extensions/bluebubbles/src/targets.ts",
|
| 852 |
+
"hashed_secret": "a3af2fb0c1e2a30bb038049e1e4b401593af6225",
|
| 853 |
+
"is_verified": false,
|
| 854 |
+
"line_number": 214
|
| 855 |
+
}
|
| 856 |
+
],
|
| 857 |
+
"extensions/copilot-proxy/index.ts": [
|
| 858 |
+
{
|
| 859 |
+
"type": "Secret Keyword",
|
| 860 |
+
"filename": "extensions/copilot-proxy/index.ts",
|
| 861 |
+
"hashed_secret": "50f013532a9770a2c2cfdc38b7581dd01df69b70",
|
| 862 |
+
"is_verified": false,
|
| 863 |
+
"line_number": 4
|
| 864 |
+
}
|
| 865 |
+
],
|
| 866 |
+
"extensions/google-antigravity-auth/index.ts": [
|
| 867 |
+
{
|
| 868 |
+
"type": "Base64 High Entropy String",
|
| 869 |
+
"filename": "extensions/google-antigravity-auth/index.ts",
|
| 870 |
+
"hashed_secret": "709d0f232b6ac4f8d24dec3e4fabfdb14257174f",
|
| 871 |
+
"is_verified": false,
|
| 872 |
+
"line_number": 9
|
| 873 |
+
}
|
| 874 |
+
],
|
| 875 |
+
"extensions/matrix/src/matrix/accounts.test.ts": [
|
| 876 |
+
{
|
| 877 |
+
"type": "Secret Keyword",
|
| 878 |
+
"filename": "extensions/matrix/src/matrix/accounts.test.ts",
|
| 879 |
+
"hashed_secret": "e5e9fa1ba31ecd1ae84f75caaa474f3a663f05f4",
|
| 880 |
+
"is_verified": false,
|
| 881 |
+
"line_number": 75
|
| 882 |
+
}
|
| 883 |
+
],
|
| 884 |
+
"extensions/matrix/src/matrix/client.test.ts": [
|
| 885 |
+
{
|
| 886 |
+
"type": "Secret Keyword",
|
| 887 |
+
"filename": "extensions/matrix/src/matrix/client.test.ts",
|
| 888 |
+
"hashed_secret": "fe7fcdaea49ece14677acd32374d2f1225819d5c",
|
| 889 |
+
"is_verified": false,
|
| 890 |
+
"line_number": 14
|
| 891 |
+
},
|
| 892 |
+
{
|
| 893 |
+
"type": "Secret Keyword",
|
| 894 |
+
"filename": "extensions/matrix/src/matrix/client.test.ts",
|
| 895 |
+
"hashed_secret": "3dc927d80543dc0f643940b70d066bd4b4c4b78e",
|
| 896 |
+
"is_verified": false,
|
| 897 |
+
"line_number": 24
|
| 898 |
+
}
|
| 899 |
+
],
|
| 900 |
+
"extensions/matrix/src/matrix/client/storage.ts": [
|
| 901 |
+
{
|
| 902 |
+
"type": "Secret Keyword",
|
| 903 |
+
"filename": "extensions/matrix/src/matrix/client/storage.ts",
|
| 904 |
+
"hashed_secret": "7505d64a54e061b7acd54ccd58b49dc43500b635",
|
| 905 |
+
"is_verified": false,
|
| 906 |
+
"line_number": 9
|
| 907 |
+
}
|
| 908 |
+
],
|
| 909 |
+
"extensions/memory-lancedb/config.ts": [
|
| 910 |
+
{
|
| 911 |
+
"type": "Secret Keyword",
|
| 912 |
+
"filename": "extensions/memory-lancedb/config.ts",
|
| 913 |
+
"hashed_secret": "ecb252044b5ea0f679ee78ec1a12904739e2904d",
|
| 914 |
+
"is_verified": false,
|
| 915 |
+
"line_number": 70
|
| 916 |
+
}
|
| 917 |
+
],
|
| 918 |
+
"extensions/memory-lancedb/index.test.ts": [
|
| 919 |
+
{
|
| 920 |
+
"type": "Secret Keyword",
|
| 921 |
+
"filename": "extensions/memory-lancedb/index.test.ts",
|
| 922 |
+
"hashed_secret": "ed65c049bb2f78ee4f703b2158ba9cc6ea31fb7e",
|
| 923 |
+
"is_verified": false,
|
| 924 |
+
"line_number": 70
|
| 925 |
+
}
|
| 926 |
+
],
|
| 927 |
+
"extensions/msteams/src/probe.test.ts": [
|
| 928 |
+
{
|
| 929 |
+
"type": "Secret Keyword",
|
| 930 |
+
"filename": "extensions/msteams/src/probe.test.ts",
|
| 931 |
+
"hashed_secret": "1a91d62f7ca67399625a4368a6ab5d4a3baa6073",
|
| 932 |
+
"is_verified": false,
|
| 933 |
+
"line_number": 34
|
| 934 |
+
}
|
| 935 |
+
],
|
| 936 |
+
"extensions/nextcloud-talk/src/accounts.ts": [
|
| 937 |
+
{
|
| 938 |
+
"type": "Secret Keyword",
|
| 939 |
+
"filename": "extensions/nextcloud-talk/src/accounts.ts",
|
| 940 |
+
"hashed_secret": "920f8f5815b381ea692e9e7c2f7119f2b1aa620a",
|
| 941 |
+
"is_verified": false,
|
| 942 |
+
"line_number": 26
|
| 943 |
+
},
|
| 944 |
+
{
|
| 945 |
+
"type": "Secret Keyword",
|
| 946 |
+
"filename": "extensions/nextcloud-talk/src/accounts.ts",
|
| 947 |
+
"hashed_secret": "71f8e7976e4cbc4561c9d62fb283e7f788202acb",
|
| 948 |
+
"is_verified": false,
|
| 949 |
+
"line_number": 139
|
| 950 |
+
}
|
| 951 |
+
],
|
| 952 |
+
"extensions/nextcloud-talk/src/channel.ts": [
|
| 953 |
+
{
|
| 954 |
+
"type": "Secret Keyword",
|
| 955 |
+
"filename": "extensions/nextcloud-talk/src/channel.ts",
|
| 956 |
+
"hashed_secret": "71f8e7976e4cbc4561c9d62fb283e7f788202acb",
|
| 957 |
+
"is_verified": false,
|
| 958 |
+
"line_number": 390
|
| 959 |
+
}
|
| 960 |
+
],
|
| 961 |
+
"extensions/nostr/README.md": [
|
| 962 |
+
{
|
| 963 |
+
"type": "Secret Keyword",
|
| 964 |
+
"filename": "extensions/nostr/README.md",
|
| 965 |
+
"hashed_secret": "edeb23e25a619c434d22bb7f1c3ca4841166b4e8",
|
| 966 |
+
"is_verified": false,
|
| 967 |
+
"line_number": 43
|
| 968 |
+
}
|
| 969 |
+
],
|
| 970 |
+
"extensions/nostr/src/channel.test.ts": [
|
| 971 |
+
{
|
| 972 |
+
"type": "Hex High Entropy String",
|
| 973 |
+
"filename": "extensions/nostr/src/channel.test.ts",
|
| 974 |
+
"hashed_secret": "ce4303f6b22257d9c9cf314ef1dee4707c6e1c13",
|
| 975 |
+
"is_verified": false,
|
| 976 |
+
"line_number": 48
|
| 977 |
+
},
|
| 978 |
+
{
|
| 979 |
+
"type": "Secret Keyword",
|
| 980 |
+
"filename": "extensions/nostr/src/channel.test.ts",
|
| 981 |
+
"hashed_secret": "ce4303f6b22257d9c9cf314ef1dee4707c6e1c13",
|
| 982 |
+
"is_verified": false,
|
| 983 |
+
"line_number": 48
|
| 984 |
+
}
|
| 985 |
+
],
|
| 986 |
+
"extensions/nostr/src/nostr-bus.fuzz.test.ts": [
|
| 987 |
+
{
|
| 988 |
+
"type": "Hex High Entropy String",
|
| 989 |
+
"filename": "extensions/nostr/src/nostr-bus.fuzz.test.ts",
|
| 990 |
+
"hashed_secret": "2b4489606a23fb31fcdc849fa7e577ba90f6d39a",
|
| 991 |
+
"is_verified": false,
|
| 992 |
+
"line_number": 202
|
| 993 |
+
},
|
| 994 |
+
{
|
| 995 |
+
"type": "Hex High Entropy String",
|
| 996 |
+
"filename": "extensions/nostr/src/nostr-bus.fuzz.test.ts",
|
| 997 |
+
"hashed_secret": "ce4303f6b22257d9c9cf314ef1dee4707c6e1c13",
|
| 998 |
+
"is_verified": false,
|
| 999 |
+
"line_number": 203
|
| 1000 |
+
},
|
| 1001 |
+
{
|
| 1002 |
+
"type": "Hex High Entropy String",
|
| 1003 |
+
"filename": "extensions/nostr/src/nostr-bus.fuzz.test.ts",
|
| 1004 |
+
"hashed_secret": "b84cb0c3925d34496e6c8b0e55b8c1664a438035",
|
| 1005 |
+
"is_verified": false,
|
| 1006 |
+
"line_number": 208
|
| 1007 |
+
}
|
| 1008 |
+
],
|
| 1009 |
+
"extensions/nostr/src/nostr-bus.test.ts": [
|
| 1010 |
+
{
|
| 1011 |
+
"type": "Hex High Entropy String",
|
| 1012 |
+
"filename": "extensions/nostr/src/nostr-bus.test.ts",
|
| 1013 |
+
"hashed_secret": "ce4303f6b22257d9c9cf314ef1dee4707c6e1c13",
|
| 1014 |
+
"is_verified": false,
|
| 1015 |
+
"line_number": 11
|
| 1016 |
+
},
|
| 1017 |
+
{
|
| 1018 |
+
"type": "Hex High Entropy String",
|
| 1019 |
+
"filename": "extensions/nostr/src/nostr-bus.test.ts",
|
| 1020 |
+
"hashed_secret": "7258e28563f03fb4c5994e8402e6f610d1f0f110",
|
| 1021 |
+
"is_verified": false,
|
| 1022 |
+
"line_number": 33
|
| 1023 |
+
},
|
| 1024 |
+
{
|
| 1025 |
+
"type": "Hex High Entropy String",
|
| 1026 |
+
"filename": "extensions/nostr/src/nostr-bus.test.ts",
|
| 1027 |
+
"hashed_secret": "2b4489606a23fb31fcdc849fa7e577ba90f6d39a",
|
| 1028 |
+
"is_verified": false,
|
| 1029 |
+
"line_number": 101
|
| 1030 |
+
},
|
| 1031 |
+
{
|
| 1032 |
+
"type": "Hex High Entropy String",
|
| 1033 |
+
"filename": "extensions/nostr/src/nostr-bus.test.ts",
|
| 1034 |
+
"hashed_secret": "ef717286343f6da3f4e6f68c6de02a5148a801c4",
|
| 1035 |
+
"is_verified": false,
|
| 1036 |
+
"line_number": 106
|
| 1037 |
+
},
|
| 1038 |
+
{
|
| 1039 |
+
"type": "Hex High Entropy String",
|
| 1040 |
+
"filename": "extensions/nostr/src/nostr-bus.test.ts",
|
| 1041 |
+
"hashed_secret": "98b35fe4c45011220f509ebb5546d3889b55a891",
|
| 1042 |
+
"is_verified": false,
|
| 1043 |
+
"line_number": 111
|
| 1044 |
+
}
|
| 1045 |
+
],
|
| 1046 |
+
"extensions/nostr/src/nostr-profile.fuzz.test.ts": [
|
| 1047 |
+
{
|
| 1048 |
+
"type": "Hex High Entropy String",
|
| 1049 |
+
"filename": "extensions/nostr/src/nostr-profile.fuzz.test.ts",
|
| 1050 |
+
"hashed_secret": "ce4303f6b22257d9c9cf314ef1dee4707c6e1c13",
|
| 1051 |
+
"is_verified": false,
|
| 1052 |
+
"line_number": 12
|
| 1053 |
+
}
|
| 1054 |
+
],
|
| 1055 |
+
"extensions/nostr/src/nostr-profile.test.ts": [
|
| 1056 |
+
{
|
| 1057 |
+
"type": "Hex High Entropy String",
|
| 1058 |
+
"filename": "extensions/nostr/src/nostr-profile.test.ts",
|
| 1059 |
+
"hashed_secret": "ce4303f6b22257d9c9cf314ef1dee4707c6e1c13",
|
| 1060 |
+
"is_verified": false,
|
| 1061 |
+
"line_number": 14
|
| 1062 |
+
}
|
| 1063 |
+
],
|
| 1064 |
+
"extensions/nostr/src/types.test.ts": [
|
| 1065 |
+
{
|
| 1066 |
+
"type": "Hex High Entropy String",
|
| 1067 |
+
"filename": "extensions/nostr/src/types.test.ts",
|
| 1068 |
+
"hashed_secret": "ce4303f6b22257d9c9cf314ef1dee4707c6e1c13",
|
| 1069 |
+
"is_verified": false,
|
| 1070 |
+
"line_number": 8
|
| 1071 |
+
},
|
| 1072 |
+
{
|
| 1073 |
+
"type": "Secret Keyword",
|
| 1074 |
+
"filename": "extensions/nostr/src/types.test.ts",
|
| 1075 |
+
"hashed_secret": "ce4303f6b22257d9c9cf314ef1dee4707c6e1c13",
|
| 1076 |
+
"is_verified": false,
|
| 1077 |
+
"line_number": 8
|
| 1078 |
+
},
|
| 1079 |
+
{
|
| 1080 |
+
"type": "Secret Keyword",
|
| 1081 |
+
"filename": "extensions/nostr/src/types.test.ts",
|
| 1082 |
+
"hashed_secret": "3bee216ebc256d692260fc3adc765050508fef5e",
|
| 1083 |
+
"is_verified": false,
|
| 1084 |
+
"line_number": 127
|
| 1085 |
+
}
|
| 1086 |
+
],
|
| 1087 |
+
"extensions/open-prose/skills/prose/SKILL.md": [
|
| 1088 |
+
{
|
| 1089 |
+
"type": "Basic Auth Credentials",
|
| 1090 |
+
"filename": "extensions/open-prose/skills/prose/SKILL.md",
|
| 1091 |
+
"hashed_secret": "9d4e1e23bd5b727046a9e3b4b7db57bd8d6ee684",
|
| 1092 |
+
"is_verified": false,
|
| 1093 |
+
"line_number": 200
|
| 1094 |
+
}
|
| 1095 |
+
],
|
| 1096 |
+
"extensions/open-prose/skills/prose/state/postgres.md": [
|
| 1097 |
+
{
|
| 1098 |
+
"type": "Secret Keyword",
|
| 1099 |
+
"filename": "extensions/open-prose/skills/prose/state/postgres.md",
|
| 1100 |
+
"hashed_secret": "fa9beb99e4029ad5a6615399e7bbae21356086b3",
|
| 1101 |
+
"is_verified": false,
|
| 1102 |
+
"line_number": 75
|
| 1103 |
+
},
|
| 1104 |
+
{
|
| 1105 |
+
"type": "Basic Auth Credentials",
|
| 1106 |
+
"filename": "extensions/open-prose/skills/prose/state/postgres.md",
|
| 1107 |
+
"hashed_secret": "9d4e1e23bd5b727046a9e3b4b7db57bd8d6ee684",
|
| 1108 |
+
"is_verified": false,
|
| 1109 |
+
"line_number": 198
|
| 1110 |
+
}
|
| 1111 |
+
],
|
| 1112 |
+
"extensions/zalo/README.md": [
|
| 1113 |
+
{
|
| 1114 |
+
"type": "Secret Keyword",
|
| 1115 |
+
"filename": "extensions/zalo/README.md",
|
| 1116 |
+
"hashed_secret": "f51aaee16a4a756d287f126b99c081b73cba7f15",
|
| 1117 |
+
"is_verified": false,
|
| 1118 |
+
"line_number": 41
|
| 1119 |
+
}
|
| 1120 |
+
],
|
| 1121 |
+
"extensions/zalo/src/monitor.webhook.test.ts": [
|
| 1122 |
+
{
|
| 1123 |
+
"type": "Secret Keyword",
|
| 1124 |
+
"filename": "extensions/zalo/src/monitor.webhook.test.ts",
|
| 1125 |
+
"hashed_secret": "e5e9fa1ba31ecd1ae84f75caaa474f3a663f05f4",
|
| 1126 |
+
"is_verified": false,
|
| 1127 |
+
"line_number": 43
|
| 1128 |
+
}
|
| 1129 |
+
],
|
| 1130 |
+
"skills/1password/references/cli-examples.md": [
|
| 1131 |
+
{
|
| 1132 |
+
"type": "Secret Keyword",
|
| 1133 |
+
"filename": "skills/1password/references/cli-examples.md",
|
| 1134 |
+
"hashed_secret": "9dda0987cc3054773a2df97e352d4f64d233ef10",
|
| 1135 |
+
"is_verified": false,
|
| 1136 |
+
"line_number": 17
|
| 1137 |
+
}
|
| 1138 |
+
],
|
| 1139 |
+
"skills/local-places/SERVER_README.md": [
|
| 1140 |
+
{
|
| 1141 |
+
"type": "Secret Keyword",
|
| 1142 |
+
"filename": "skills/local-places/SERVER_README.md",
|
| 1143 |
+
"hashed_secret": "6d9c68c603e465077bdd49c62347fe54717f83a3",
|
| 1144 |
+
"is_verified": false,
|
| 1145 |
+
"line_number": 28
|
| 1146 |
+
}
|
| 1147 |
+
],
|
| 1148 |
+
"skills/openai-whisper-api/SKILL.md": [
|
| 1149 |
+
{
|
| 1150 |
+
"type": "Secret Keyword",
|
| 1151 |
+
"filename": "skills/openai-whisper-api/SKILL.md",
|
| 1152 |
+
"hashed_secret": "1077361f94d70e1ddcc7c6dc581a489532a81d03",
|
| 1153 |
+
"is_verified": false,
|
| 1154 |
+
"line_number": 39
|
| 1155 |
+
}
|
| 1156 |
+
],
|
| 1157 |
+
"skills/trello/SKILL.md": [
|
| 1158 |
+
{
|
| 1159 |
+
"type": "Secret Keyword",
|
| 1160 |
+
"filename": "skills/trello/SKILL.md",
|
| 1161 |
+
"hashed_secret": "11fa7c37d697f30e6aee828b4426a10f83ab2380",
|
| 1162 |
+
"is_verified": false,
|
| 1163 |
+
"line_number": 18
|
| 1164 |
+
}
|
| 1165 |
+
],
|
| 1166 |
+
"src/agents/memory-search.test.ts": [
|
| 1167 |
+
{
|
| 1168 |
+
"type": "Secret Keyword",
|
| 1169 |
+
"filename": "src/agents/memory-search.test.ts",
|
| 1170 |
+
"hashed_secret": "a1b49d68a91fdf9c9217773f3fac988d77fa0f50",
|
| 1171 |
+
"is_verified": false,
|
| 1172 |
+
"line_number": 164
|
| 1173 |
+
}
|
| 1174 |
+
],
|
| 1175 |
+
"src/agents/model-auth.test.ts": [
|
| 1176 |
+
{
|
| 1177 |
+
"type": "Secret Keyword",
|
| 1178 |
+
"filename": "src/agents/model-auth.test.ts",
|
| 1179 |
+
"hashed_secret": "07a6b9cec637c806195e8aa7e5c0851ab03dc35e",
|
| 1180 |
+
"is_verified": false,
|
| 1181 |
+
"line_number": 211
|
| 1182 |
+
},
|
| 1183 |
+
{
|
| 1184 |
+
"type": "Secret Keyword",
|
| 1185 |
+
"filename": "src/agents/model-auth.test.ts",
|
| 1186 |
+
"hashed_secret": "21f296583ccd80c5ab9b3330a8b0d47e4a409fb9",
|
| 1187 |
+
"is_verified": false,
|
| 1188 |
+
"line_number": 240
|
| 1189 |
+
},
|
| 1190 |
+
{
|
| 1191 |
+
"type": "Secret Keyword",
|
| 1192 |
+
"filename": "src/agents/model-auth.test.ts",
|
| 1193 |
+
"hashed_secret": "77e991e9f56e6fa4ed1a908208048421f1214c07",
|
| 1194 |
+
"is_verified": false,
|
| 1195 |
+
"line_number": 264
|
| 1196 |
+
},
|
| 1197 |
+
{
|
| 1198 |
+
"type": "Secret Keyword",
|
| 1199 |
+
"filename": "src/agents/model-auth.test.ts",
|
| 1200 |
+
"hashed_secret": "dff6d4ff5dc357cf451d1855ab9cbda562645c9f",
|
| 1201 |
+
"is_verified": false,
|
| 1202 |
+
"line_number": 295
|
| 1203 |
+
}
|
| 1204 |
+
],
|
| 1205 |
+
"src/agents/model-auth.ts": [
|
| 1206 |
+
{
|
| 1207 |
+
"type": "Secret Keyword",
|
| 1208 |
+
"filename": "src/agents/model-auth.ts",
|
| 1209 |
+
"hashed_secret": "8956265d216d474a080edaa97880d37fc1386f33",
|
| 1210 |
+
"is_verified": false,
|
| 1211 |
+
"line_number": 22
|
| 1212 |
+
}
|
| 1213 |
+
],
|
| 1214 |
+
"src/agents/models-config.auto-injects-github-copilot-provider-token-is.test.ts": [
|
| 1215 |
+
{
|
| 1216 |
+
"type": "Secret Keyword",
|
| 1217 |
+
"filename": "src/agents/models-config.auto-injects-github-copilot-provider-token-is.test.ts",
|
| 1218 |
+
"hashed_secret": "7cf31e8b6cda49f70c31f1f25af05d46f924142d",
|
| 1219 |
+
"is_verified": false,
|
| 1220 |
+
"line_number": 16
|
| 1221 |
+
}
|
| 1222 |
+
],
|
| 1223 |
+
"src/agents/models-config.falls-back-default-baseurl-token-exchange-fails.test.ts": [
|
| 1224 |
+
{
|
| 1225 |
+
"type": "Secret Keyword",
|
| 1226 |
+
"filename": "src/agents/models-config.falls-back-default-baseurl-token-exchange-fails.test.ts",
|
| 1227 |
+
"hashed_secret": "7cf31e8b6cda49f70c31f1f25af05d46f924142d",
|
| 1228 |
+
"is_verified": false,
|
| 1229 |
+
"line_number": 16
|
| 1230 |
+
}
|
| 1231 |
+
],
|
| 1232 |
+
"src/agents/models-config.fills-missing-provider-apikey-from-env-var.test.ts": [
|
| 1233 |
+
{
|
| 1234 |
+
"type": "Secret Keyword",
|
| 1235 |
+
"filename": "src/agents/models-config.fills-missing-provider-apikey-from-env-var.test.ts",
|
| 1236 |
+
"hashed_secret": "7cf31e8b6cda49f70c31f1f25af05d46f924142d",
|
| 1237 |
+
"is_verified": false,
|
| 1238 |
+
"line_number": 16
|
| 1239 |
+
},
|
| 1240 |
+
{
|
| 1241 |
+
"type": "Secret Keyword",
|
| 1242 |
+
"filename": "src/agents/models-config.fills-missing-provider-apikey-from-env-var.test.ts",
|
| 1243 |
+
"hashed_secret": "fcdd655b11f33ba4327695084a347b2ba192976c",
|
| 1244 |
+
"is_verified": false,
|
| 1245 |
+
"line_number": 50
|
| 1246 |
+
},
|
| 1247 |
+
{
|
| 1248 |
+
"type": "Secret Keyword",
|
| 1249 |
+
"filename": "src/agents/models-config.fills-missing-provider-apikey-from-env-var.test.ts",
|
| 1250 |
+
"hashed_secret": "3a81eb091f80c845232225be5663d270e90dacb7",
|
| 1251 |
+
"is_verified": false,
|
| 1252 |
+
"line_number": 108
|
| 1253 |
+
}
|
| 1254 |
+
],
|
| 1255 |
+
"src/agents/models-config.normalizes-gemini-3-ids-preview-google-providers.test.ts": [
|
| 1256 |
+
{
|
| 1257 |
+
"type": "Secret Keyword",
|
| 1258 |
+
"filename": "src/agents/models-config.normalizes-gemini-3-ids-preview-google-providers.test.ts",
|
| 1259 |
+
"hashed_secret": "7cf31e8b6cda49f70c31f1f25af05d46f924142d",
|
| 1260 |
+
"is_verified": false,
|
| 1261 |
+
"line_number": 16
|
| 1262 |
+
},
|
| 1263 |
+
{
|
| 1264 |
+
"type": "Secret Keyword",
|
| 1265 |
+
"filename": "src/agents/models-config.normalizes-gemini-3-ids-preview-google-providers.test.ts",
|
| 1266 |
+
"hashed_secret": "980d02eb9335ae7c9e9984f6c8ad432352a0d2ac",
|
| 1267 |
+
"is_verified": false,
|
| 1268 |
+
"line_number": 57
|
| 1269 |
+
}
|
| 1270 |
+
],
|
| 1271 |
+
"src/agents/models-config.skips-writing-models-json-no-env-token.test.ts": [
|
| 1272 |
+
{
|
| 1273 |
+
"type": "Secret Keyword",
|
| 1274 |
+
"filename": "src/agents/models-config.skips-writing-models-json-no-env-token.test.ts",
|
| 1275 |
+
"hashed_secret": "7cf31e8b6cda49f70c31f1f25af05d46f924142d",
|
| 1276 |
+
"is_verified": false,
|
| 1277 |
+
"line_number": 16
|
| 1278 |
+
},
|
| 1279 |
+
{
|
| 1280 |
+
"type": "Secret Keyword",
|
| 1281 |
+
"filename": "src/agents/models-config.skips-writing-models-json-no-env-token.test.ts",
|
| 1282 |
+
"hashed_secret": "fcdd655b11f33ba4327695084a347b2ba192976c",
|
| 1283 |
+
"is_verified": false,
|
| 1284 |
+
"line_number": 112
|
| 1285 |
+
},
|
| 1286 |
+
{
|
| 1287 |
+
"type": "Secret Keyword",
|
| 1288 |
+
"filename": "src/agents/models-config.skips-writing-models-json-no-env-token.test.ts",
|
| 1289 |
+
"hashed_secret": "94c4be5a1976115e8152960c21e04400a4fccdf6",
|
| 1290 |
+
"is_verified": false,
|
| 1291 |
+
"line_number": 146
|
| 1292 |
+
}
|
| 1293 |
+
],
|
| 1294 |
+
"src/agents/models-config.uses-first-github-copilot-profile-env-tokens.test.ts": [
|
| 1295 |
+
{
|
| 1296 |
+
"type": "Secret Keyword",
|
| 1297 |
+
"filename": "src/agents/models-config.uses-first-github-copilot-profile-env-tokens.test.ts",
|
| 1298 |
+
"hashed_secret": "7cf31e8b6cda49f70c31f1f25af05d46f924142d",
|
| 1299 |
+
"is_verified": false,
|
| 1300 |
+
"line_number": 16
|
| 1301 |
+
}
|
| 1302 |
+
],
|
| 1303 |
+
"src/agents/openai-responses.reasoning-replay.test.ts": [
|
| 1304 |
+
{
|
| 1305 |
+
"type": "Secret Keyword",
|
| 1306 |
+
"filename": "src/agents/openai-responses.reasoning-replay.test.ts",
|
| 1307 |
+
"hashed_secret": "a94a8fe5ccb19ba61c4c0873d391e987982fbbd3",
|
| 1308 |
+
"is_verified": false,
|
| 1309 |
+
"line_number": 124
|
| 1310 |
+
}
|
| 1311 |
+
],
|
| 1312 |
+
"src/agents/pi-embedded-runner.applygoogleturnorderingfix.test.ts": [
|
| 1313 |
+
{
|
| 1314 |
+
"type": "Secret Keyword",
|
| 1315 |
+
"filename": "src/agents/pi-embedded-runner.applygoogleturnorderingfix.test.ts",
|
| 1316 |
+
"hashed_secret": "e9a5f12a8ecbb3eb46eca5096b5c52aa5e7c9fdd",
|
| 1317 |
+
"is_verified": false,
|
| 1318 |
+
"line_number": 58
|
| 1319 |
+
}
|
| 1320 |
+
],
|
| 1321 |
+
"src/agents/pi-embedded-runner.buildembeddedsandboxinfo.test.ts": [
|
| 1322 |
+
{
|
| 1323 |
+
"type": "Secret Keyword",
|
| 1324 |
+
"filename": "src/agents/pi-embedded-runner.buildembeddedsandboxinfo.test.ts",
|
| 1325 |
+
"hashed_secret": "e9a5f12a8ecbb3eb46eca5096b5c52aa5e7c9fdd",
|
| 1326 |
+
"is_verified": false,
|
| 1327 |
+
"line_number": 57
|
| 1328 |
+
}
|
| 1329 |
+
],
|
| 1330 |
+
"src/agents/pi-embedded-runner.createsystempromptoverride.test.ts": [
|
| 1331 |
+
{
|
| 1332 |
+
"type": "Secret Keyword",
|
| 1333 |
+
"filename": "src/agents/pi-embedded-runner.createsystempromptoverride.test.ts",
|
| 1334 |
+
"hashed_secret": "e9a5f12a8ecbb3eb46eca5096b5c52aa5e7c9fdd",
|
| 1335 |
+
"is_verified": false,
|
| 1336 |
+
"line_number": 56
|
| 1337 |
+
}
|
| 1338 |
+
],
|
| 1339 |
+
"src/agents/pi-embedded-runner.get-dm-history-limit-from-session-key.falls-back-provider-default-per-dm-not.test.ts": [
|
| 1340 |
+
{
|
| 1341 |
+
"type": "Secret Keyword",
|
| 1342 |
+
"filename": "src/agents/pi-embedded-runner.get-dm-history-limit-from-session-key.falls-back-provider-default-per-dm-not.test.ts",
|
| 1343 |
+
"hashed_secret": "e9a5f12a8ecbb3eb46eca5096b5c52aa5e7c9fdd",
|
| 1344 |
+
"is_verified": false,
|
| 1345 |
+
"line_number": 56
|
| 1346 |
+
}
|
| 1347 |
+
],
|
| 1348 |
+
"src/agents/pi-embedded-runner.get-dm-history-limit-from-session-key.returns-undefined-sessionkey-is-undefined.test.ts": [
|
| 1349 |
+
{
|
| 1350 |
+
"type": "Secret Keyword",
|
| 1351 |
+
"filename": "src/agents/pi-embedded-runner.get-dm-history-limit-from-session-key.returns-undefined-sessionkey-is-undefined.test.ts",
|
| 1352 |
+
"hashed_secret": "e9a5f12a8ecbb3eb46eca5096b5c52aa5e7c9fdd",
|
| 1353 |
+
"is_verified": false,
|
| 1354 |
+
"line_number": 56
|
| 1355 |
+
}
|
| 1356 |
+
],
|
| 1357 |
+
"src/agents/pi-embedded-runner.limithistoryturns.test.ts": [
|
| 1358 |
+
{
|
| 1359 |
+
"type": "Secret Keyword",
|
| 1360 |
+
"filename": "src/agents/pi-embedded-runner.limithistoryturns.test.ts",
|
| 1361 |
+
"hashed_secret": "e9a5f12a8ecbb3eb46eca5096b5c52aa5e7c9fdd",
|
| 1362 |
+
"is_verified": false,
|
| 1363 |
+
"line_number": 57
|
| 1364 |
+
}
|
| 1365 |
+
],
|
| 1366 |
+
"src/agents/pi-embedded-runner.resolvesessionagentids.test.ts": [
|
| 1367 |
+
{
|
| 1368 |
+
"type": "Secret Keyword",
|
| 1369 |
+
"filename": "src/agents/pi-embedded-runner.resolvesessionagentids.test.ts",
|
| 1370 |
+
"hashed_secret": "e9a5f12a8ecbb3eb46eca5096b5c52aa5e7c9fdd",
|
| 1371 |
+
"is_verified": false,
|
| 1372 |
+
"line_number": 56
|
| 1373 |
+
}
|
| 1374 |
+
],
|
| 1375 |
+
"src/agents/pi-embedded-runner.splitsdktools.test.ts": [
|
| 1376 |
+
{
|
| 1377 |
+
"type": "Secret Keyword",
|
| 1378 |
+
"filename": "src/agents/pi-embedded-runner.splitsdktools.test.ts",
|
| 1379 |
+
"hashed_secret": "e9a5f12a8ecbb3eb46eca5096b5c52aa5e7c9fdd",
|
| 1380 |
+
"is_verified": false,
|
| 1381 |
+
"line_number": 57
|
| 1382 |
+
}
|
| 1383 |
+
],
|
| 1384 |
+
"src/agents/pi-embedded-runner.test.ts": [
|
| 1385 |
+
{
|
| 1386 |
+
"type": "Secret Keyword",
|
| 1387 |
+
"filename": "src/agents/pi-embedded-runner.test.ts",
|
| 1388 |
+
"hashed_secret": "e9a5f12a8ecbb3eb46eca5096b5c52aa5e7c9fdd",
|
| 1389 |
+
"is_verified": false,
|
| 1390 |
+
"line_number": 117
|
| 1391 |
+
},
|
| 1392 |
+
{
|
| 1393 |
+
"type": "Secret Keyword",
|
| 1394 |
+
"filename": "src/agents/pi-embedded-runner.test.ts",
|
| 1395 |
+
"hashed_secret": "fcdd655b11f33ba4327695084a347b2ba192976c",
|
| 1396 |
+
"is_verified": false,
|
| 1397 |
+
"line_number": 178
|
| 1398 |
+
}
|
| 1399 |
+
],
|
| 1400 |
+
"src/agents/skills.applyskillenvoverrides.test.ts": [
|
| 1401 |
+
{
|
| 1402 |
+
"type": "Secret Keyword",
|
| 1403 |
+
"filename": "src/agents/skills.applyskillenvoverrides.test.ts",
|
| 1404 |
+
"hashed_secret": "5df3a673d724e8a1eb673a8baf623e183940804d",
|
| 1405 |
+
"is_verified": false,
|
| 1406 |
+
"line_number": 54
|
| 1407 |
+
},
|
| 1408 |
+
{
|
| 1409 |
+
"type": "Secret Keyword",
|
| 1410 |
+
"filename": "src/agents/skills.applyskillenvoverrides.test.ts",
|
| 1411 |
+
"hashed_secret": "8921daaa546693e52bc1f9c40bdcf15e816e0448",
|
| 1412 |
+
"is_verified": false,
|
| 1413 |
+
"line_number": 80
|
| 1414 |
+
}
|
| 1415 |
+
],
|
| 1416 |
+
"src/agents/skills.build-workspace-skills-prompt.prefers-workspace-skills-managed-skills.test.ts": [
|
| 1417 |
+
{
|
| 1418 |
+
"type": "Secret Keyword",
|
| 1419 |
+
"filename": "src/agents/skills.build-workspace-skills-prompt.prefers-workspace-skills-managed-skills.test.ts",
|
| 1420 |
+
"hashed_secret": "7a85f4764bbd6daf1c3545efbbf0f279a6dc0beb",
|
| 1421 |
+
"is_verified": false,
|
| 1422 |
+
"line_number": 124
|
| 1423 |
+
}
|
| 1424 |
+
],
|
| 1425 |
+
"src/agents/skills.build-workspace-skills-prompt.syncs-merged-skills-into-target-workspace.test.ts": [
|
| 1426 |
+
{
|
| 1427 |
+
"type": "Secret Keyword",
|
| 1428 |
+
"filename": "src/agents/skills.build-workspace-skills-prompt.syncs-merged-skills-into-target-workspace.test.ts",
|
| 1429 |
+
"hashed_secret": "3acfb2c2b433c0ea7ff107e33df91b18e52f960f",
|
| 1430 |
+
"is_verified": false,
|
| 1431 |
+
"line_number": 102
|
| 1432 |
+
}
|
| 1433 |
+
],
|
| 1434 |
+
"src/agents/tools/web-fetch.ssrf.test.ts": [
|
| 1435 |
+
{
|
| 1436 |
+
"type": "Secret Keyword",
|
| 1437 |
+
"filename": "src/agents/tools/web-fetch.ssrf.test.ts",
|
| 1438 |
+
"hashed_secret": "5ce8e9d54c77266fff990194d2219a708c59b76c",
|
| 1439 |
+
"is_verified": false,
|
| 1440 |
+
"line_number": 55
|
| 1441 |
+
}
|
| 1442 |
+
],
|
| 1443 |
+
"src/agents/tools/web-search.ts": [
|
| 1444 |
+
{
|
| 1445 |
+
"type": "Secret Keyword",
|
| 1446 |
+
"filename": "src/agents/tools/web-search.ts",
|
| 1447 |
+
"hashed_secret": "dfba7aade0868074c2861c98e2a9a92f3178a51b",
|
| 1448 |
+
"is_verified": false,
|
| 1449 |
+
"line_number": 85
|
| 1450 |
+
},
|
| 1451 |
+
{
|
| 1452 |
+
"type": "Secret Keyword",
|
| 1453 |
+
"filename": "src/agents/tools/web-search.ts",
|
| 1454 |
+
"hashed_secret": "71f8e7976e4cbc4561c9d62fb283e7f788202acb",
|
| 1455 |
+
"is_verified": false,
|
| 1456 |
+
"line_number": 190
|
| 1457 |
+
},
|
| 1458 |
+
{
|
| 1459 |
+
"type": "Secret Keyword",
|
| 1460 |
+
"filename": "src/agents/tools/web-search.ts",
|
| 1461 |
+
"hashed_secret": "c4865ff9250aca23b0d98eb079dad70ebec1cced",
|
| 1462 |
+
"is_verified": false,
|
| 1463 |
+
"line_number": 198
|
| 1464 |
+
},
|
| 1465 |
+
{
|
| 1466 |
+
"type": "Secret Keyword",
|
| 1467 |
+
"filename": "src/agents/tools/web-search.ts",
|
| 1468 |
+
"hashed_secret": "527ee41f36386e85fa932ef09471ca017f3c95c8",
|
| 1469 |
+
"is_verified": false,
|
| 1470 |
+
"line_number": 199
|
| 1471 |
+
}
|
| 1472 |
+
],
|
| 1473 |
+
"src/agents/tools/web-tools.enabled-defaults.test.ts": [
|
| 1474 |
+
{
|
| 1475 |
+
"type": "Secret Keyword",
|
| 1476 |
+
"filename": "src/agents/tools/web-tools.enabled-defaults.test.ts",
|
| 1477 |
+
"hashed_secret": "47b249a75ca78fdb578d0f28c33685e27ea82684",
|
| 1478 |
+
"is_verified": false,
|
| 1479 |
+
"line_number": 213
|
| 1480 |
+
},
|
| 1481 |
+
{
|
| 1482 |
+
"type": "Secret Keyword",
|
| 1483 |
+
"filename": "src/agents/tools/web-tools.enabled-defaults.test.ts",
|
| 1484 |
+
"hashed_secret": "d0ffd81d6d7ad1bc3c365660fe8882480c9a986e",
|
| 1485 |
+
"is_verified": false,
|
| 1486 |
+
"line_number": 242
|
| 1487 |
+
}
|
| 1488 |
+
],
|
| 1489 |
+
"src/agents/tools/web-tools.fetch.test.ts": [
|
| 1490 |
+
{
|
| 1491 |
+
"type": "Secret Keyword",
|
| 1492 |
+
"filename": "src/agents/tools/web-tools.fetch.test.ts",
|
| 1493 |
+
"hashed_secret": "5ce8e9d54c77266fff990194d2219a708c59b76c",
|
| 1494 |
+
"is_verified": false,
|
| 1495 |
+
"line_number": 101
|
| 1496 |
+
}
|
| 1497 |
+
],
|
| 1498 |
+
"src/auto-reply/reply.directive.directive-behavior.prefers-alias-matches-fuzzy-selection-is-ambiguous.e2e.test.ts": [
|
| 1499 |
+
{
|
| 1500 |
+
"type": "Secret Keyword",
|
| 1501 |
+
"filename": "src/auto-reply/reply.directive.directive-behavior.prefers-alias-matches-fuzzy-selection-is-ambiguous.e2e.test.ts",
|
| 1502 |
+
"hashed_secret": "e9a5f12a8ecbb3eb46eca5096b5c52aa5e7c9fdd",
|
| 1503 |
+
"is_verified": false,
|
| 1504 |
+
"line_number": 90
|
| 1505 |
+
},
|
| 1506 |
+
{
|
| 1507 |
+
"type": "Secret Keyword",
|
| 1508 |
+
"filename": "src/auto-reply/reply.directive.directive-behavior.prefers-alias-matches-fuzzy-selection-is-ambiguous.e2e.test.ts",
|
| 1509 |
+
"hashed_secret": "16c249e04e2be318050cb883c40137361c0c7209",
|
| 1510 |
+
"is_verified": false,
|
| 1511 |
+
"line_number": 96
|
| 1512 |
+
}
|
| 1513 |
+
],
|
| 1514 |
+
"src/auto-reply/reply.directive.directive-behavior.supports-fuzzy-model-matches-model-directive.e2e.test.ts": [
|
| 1515 |
+
{
|
| 1516 |
+
"type": "Secret Keyword",
|
| 1517 |
+
"filename": "src/auto-reply/reply.directive.directive-behavior.supports-fuzzy-model-matches-model-directive.e2e.test.ts",
|
| 1518 |
+
"hashed_secret": "e9a5f12a8ecbb3eb46eca5096b5c52aa5e7c9fdd",
|
| 1519 |
+
"is_verified": false,
|
| 1520 |
+
"line_number": 87
|
| 1521 |
+
},
|
| 1522 |
+
{
|
| 1523 |
+
"type": "Secret Keyword",
|
| 1524 |
+
"filename": "src/auto-reply/reply.directive.directive-behavior.supports-fuzzy-model-matches-model-directive.e2e.test.ts",
|
| 1525 |
+
"hashed_secret": "16c249e04e2be318050cb883c40137361c0c7209",
|
| 1526 |
+
"is_verified": false,
|
| 1527 |
+
"line_number": 228
|
| 1528 |
+
}
|
| 1529 |
+
],
|
| 1530 |
+
"src/auto-reply/status.test.ts": [
|
| 1531 |
+
{
|
| 1532 |
+
"type": "Secret Keyword",
|
| 1533 |
+
"filename": "src/auto-reply/status.test.ts",
|
| 1534 |
+
"hashed_secret": "3acfb2c2b433c0ea7ff107e33df91b18e52f960f",
|
| 1535 |
+
"is_verified": false,
|
| 1536 |
+
"line_number": 20
|
| 1537 |
+
}
|
| 1538 |
+
],
|
| 1539 |
+
"src/browser/cdp.helpers.test.ts": [
|
| 1540 |
+
{
|
| 1541 |
+
"type": "Basic Auth Credentials",
|
| 1542 |
+
"filename": "src/browser/cdp.helpers.test.ts",
|
| 1543 |
+
"hashed_secret": "9d4e1e23bd5b727046a9e3b4b7db57bd8d6ee684",
|
| 1544 |
+
"is_verified": false,
|
| 1545 |
+
"line_number": 22
|
| 1546 |
+
}
|
| 1547 |
+
],
|
| 1548 |
+
"src/browser/cdp.test.ts": [
|
| 1549 |
+
{
|
| 1550 |
+
"type": "Basic Auth Credentials",
|
| 1551 |
+
"filename": "src/browser/cdp.test.ts",
|
| 1552 |
+
"hashed_secret": "9d4e1e23bd5b727046a9e3b4b7db57bd8d6ee684",
|
| 1553 |
+
"is_verified": false,
|
| 1554 |
+
"line_number": 172
|
| 1555 |
+
}
|
| 1556 |
+
],
|
| 1557 |
+
"src/browser/target-id.test.ts": [
|
| 1558 |
+
{
|
| 1559 |
+
"type": "Hex High Entropy String",
|
| 1560 |
+
"filename": "src/browser/target-id.test.ts",
|
| 1561 |
+
"hashed_secret": "4e126c049580d66ca1549fa534d95a7263f27f46",
|
| 1562 |
+
"is_verified": false,
|
| 1563 |
+
"line_number": 13
|
| 1564 |
+
}
|
| 1565 |
+
],
|
| 1566 |
+
"src/cli/update-cli.test.ts": [
|
| 1567 |
+
{
|
| 1568 |
+
"type": "Hex High Entropy String",
|
| 1569 |
+
"filename": "src/cli/update-cli.test.ts",
|
| 1570 |
+
"hashed_secret": "e4f91dd323bac5bfc4f60a6e433787671dc2421d",
|
| 1571 |
+
"is_verified": false,
|
| 1572 |
+
"line_number": 112
|
| 1573 |
+
}
|
| 1574 |
+
],
|
| 1575 |
+
"src/commands/auth-choice.preferred-provider.ts": [
|
| 1576 |
+
{
|
| 1577 |
+
"type": "Secret Keyword",
|
| 1578 |
+
"filename": "src/commands/auth-choice.preferred-provider.ts",
|
| 1579 |
+
"hashed_secret": "c03a8d10174dd7eb2b3288b570a5a74fdd9ae05d",
|
| 1580 |
+
"is_verified": false,
|
| 1581 |
+
"line_number": 8
|
| 1582 |
+
}
|
| 1583 |
+
],
|
| 1584 |
+
"src/commands/auth-choice.test.ts": [
|
| 1585 |
+
{
|
| 1586 |
+
"type": "Secret Keyword",
|
| 1587 |
+
"filename": "src/commands/auth-choice.test.ts",
|
| 1588 |
+
"hashed_secret": "2480500ff391183070fe22ba8665a8be19350833",
|
| 1589 |
+
"is_verified": false,
|
| 1590 |
+
"line_number": 289
|
| 1591 |
+
},
|
| 1592 |
+
{
|
| 1593 |
+
"type": "Secret Keyword",
|
| 1594 |
+
"filename": "src/commands/auth-choice.test.ts",
|
| 1595 |
+
"hashed_secret": "77e991e9f56e6fa4ed1a908208048421f1214c07",
|
| 1596 |
+
"is_verified": false,
|
| 1597 |
+
"line_number": 350
|
| 1598 |
+
},
|
| 1599 |
+
{
|
| 1600 |
+
"type": "Secret Keyword",
|
| 1601 |
+
"filename": "src/commands/auth-choice.test.ts",
|
| 1602 |
+
"hashed_secret": "1b4d8423b11d32dd0c466428ac81de84a4a9442b",
|
| 1603 |
+
"is_verified": false,
|
| 1604 |
+
"line_number": 528
|
| 1605 |
+
}
|
| 1606 |
+
],
|
| 1607 |
+
"src/commands/configure.gateway-auth.test.ts": [
|
| 1608 |
+
{
|
| 1609 |
+
"type": "Secret Keyword",
|
| 1610 |
+
"filename": "src/commands/configure.gateway-auth.test.ts",
|
| 1611 |
+
"hashed_secret": "e5e9fa1ba31ecd1ae84f75caaa474f3a663f05f4",
|
| 1612 |
+
"is_verified": false,
|
| 1613 |
+
"line_number": 8
|
| 1614 |
+
}
|
| 1615 |
+
],
|
| 1616 |
+
"src/commands/models/list.status.test.ts": [
|
| 1617 |
+
{
|
| 1618 |
+
"type": "Base64 High Entropy String",
|
| 1619 |
+
"filename": "src/commands/models/list.status.test.ts",
|
| 1620 |
+
"hashed_secret": "d6ae2508a78a232d5378ef24b85ce40cbb4d7ff0",
|
| 1621 |
+
"is_verified": false,
|
| 1622 |
+
"line_number": 11
|
| 1623 |
+
},
|
| 1624 |
+
{
|
| 1625 |
+
"type": "Base64 High Entropy String",
|
| 1626 |
+
"filename": "src/commands/models/list.status.test.ts",
|
| 1627 |
+
"hashed_secret": "2d8012102440ea97852b3152239218f00579bafa",
|
| 1628 |
+
"is_verified": false,
|
| 1629 |
+
"line_number": 18
|
| 1630 |
+
},
|
| 1631 |
+
{
|
| 1632 |
+
"type": "Base64 High Entropy String",
|
| 1633 |
+
"filename": "src/commands/models/list.status.test.ts",
|
| 1634 |
+
"hashed_secret": "51848e2be4b461a549218d3167f19c01be6b98b8",
|
| 1635 |
+
"is_verified": false,
|
| 1636 |
+
"line_number": 46
|
| 1637 |
+
},
|
| 1638 |
+
{
|
| 1639 |
+
"type": "Secret Keyword",
|
| 1640 |
+
"filename": "src/commands/models/list.status.test.ts",
|
| 1641 |
+
"hashed_secret": "51848e2be4b461a549218d3167f19c01be6b98b8",
|
| 1642 |
+
"is_verified": false,
|
| 1643 |
+
"line_number": 46
|
| 1644 |
+
},
|
| 1645 |
+
{
|
| 1646 |
+
"type": "Secret Keyword",
|
| 1647 |
+
"filename": "src/commands/models/list.status.test.ts",
|
| 1648 |
+
"hashed_secret": "1c1e381bfb72d3b7bfca9437053d9875356680f0",
|
| 1649 |
+
"is_verified": false,
|
| 1650 |
+
"line_number": 52
|
| 1651 |
+
}
|
| 1652 |
+
],
|
| 1653 |
+
"src/commands/onboard-auth.config-minimax.ts": [
|
| 1654 |
+
{
|
| 1655 |
+
"type": "Secret Keyword",
|
| 1656 |
+
"filename": "src/commands/onboard-auth.config-minimax.ts",
|
| 1657 |
+
"hashed_secret": "16c249e04e2be318050cb883c40137361c0c7209",
|
| 1658 |
+
"is_verified": false,
|
| 1659 |
+
"line_number": 30
|
| 1660 |
+
},
|
| 1661 |
+
{
|
| 1662 |
+
"type": "Secret Keyword",
|
| 1663 |
+
"filename": "src/commands/onboard-auth.config-minimax.ts",
|
| 1664 |
+
"hashed_secret": "ddcb713196b974770575a9bea5a4e7d46361f8e9",
|
| 1665 |
+
"is_verified": false,
|
| 1666 |
+
"line_number": 85
|
| 1667 |
+
}
|
| 1668 |
+
],
|
| 1669 |
+
"src/commands/onboard-auth.test.ts": [
|
| 1670 |
+
{
|
| 1671 |
+
"type": "Secret Keyword",
|
| 1672 |
+
"filename": "src/commands/onboard-auth.test.ts",
|
| 1673 |
+
"hashed_secret": "666c100dab549a6f56da7da546bd848ed5086541",
|
| 1674 |
+
"is_verified": false,
|
| 1675 |
+
"line_number": 230
|
| 1676 |
+
},
|
| 1677 |
+
{
|
| 1678 |
+
"type": "Secret Keyword",
|
| 1679 |
+
"filename": "src/commands/onboard-auth.test.ts",
|
| 1680 |
+
"hashed_secret": "e184b402822abc549b37689c84e8e0e33c39a1f1",
|
| 1681 |
+
"is_verified": false,
|
| 1682 |
+
"line_number": 262
|
| 1683 |
+
}
|
| 1684 |
+
],
|
| 1685 |
+
"src/commands/onboard-non-interactive.ai-gateway.test.ts": [
|
| 1686 |
+
{
|
| 1687 |
+
"type": "Secret Keyword",
|
| 1688 |
+
"filename": "src/commands/onboard-non-interactive.ai-gateway.test.ts",
|
| 1689 |
+
"hashed_secret": "77e991e9f56e6fa4ed1a908208048421f1214c07",
|
| 1690 |
+
"is_verified": false,
|
| 1691 |
+
"line_number": 50
|
| 1692 |
+
}
|
| 1693 |
+
],
|
| 1694 |
+
"src/commands/onboard-non-interactive/api-keys.ts": [
|
| 1695 |
+
{
|
| 1696 |
+
"type": "Secret Keyword",
|
| 1697 |
+
"filename": "src/commands/onboard-non-interactive/api-keys.ts",
|
| 1698 |
+
"hashed_secret": "112f3a99b283a4e1788dedd8e0e5d35375c33747",
|
| 1699 |
+
"is_verified": false,
|
| 1700 |
+
"line_number": 10
|
| 1701 |
+
}
|
| 1702 |
+
],
|
| 1703 |
+
"src/config/config.env-vars.test.ts": [
|
| 1704 |
+
{
|
| 1705 |
+
"type": "Secret Keyword",
|
| 1706 |
+
"filename": "src/config/config.env-vars.test.ts",
|
| 1707 |
+
"hashed_secret": "a24ef9c1a27cac44823571ceef2e8262718eee36",
|
| 1708 |
+
"is_verified": false,
|
| 1709 |
+
"line_number": 15
|
| 1710 |
+
},
|
| 1711 |
+
{
|
| 1712 |
+
"type": "Secret Keyword",
|
| 1713 |
+
"filename": "src/config/config.env-vars.test.ts",
|
| 1714 |
+
"hashed_secret": "29d5f92e9ee44d4854d6dfaeefc3dc27d779fdf3",
|
| 1715 |
+
"is_verified": false,
|
| 1716 |
+
"line_number": 47
|
| 1717 |
+
},
|
| 1718 |
+
{
|
| 1719 |
+
"type": "Secret Keyword",
|
| 1720 |
+
"filename": "src/config/config.env-vars.test.ts",
|
| 1721 |
+
"hashed_secret": "1672b6a1e7956c6a70f45d699aa42a351b1f8b80",
|
| 1722 |
+
"is_verified": false,
|
| 1723 |
+
"line_number": 63
|
| 1724 |
+
}
|
| 1725 |
+
],
|
| 1726 |
+
"src/config/config.talk-api-key-fallback.test.ts": [
|
| 1727 |
+
{
|
| 1728 |
+
"type": "Secret Keyword",
|
| 1729 |
+
"filename": "src/config/config.talk-api-key-fallback.test.ts",
|
| 1730 |
+
"hashed_secret": "bea2f7b64fab8d1d414d0449530b1e088d36d5b1",
|
| 1731 |
+
"is_verified": false,
|
| 1732 |
+
"line_number": 42
|
| 1733 |
+
}
|
| 1734 |
+
],
|
| 1735 |
+
"src/config/config.web-search-provider.test.ts": [
|
| 1736 |
+
{
|
| 1737 |
+
"type": "Secret Keyword",
|
| 1738 |
+
"filename": "src/config/config.web-search-provider.test.ts",
|
| 1739 |
+
"hashed_secret": "3acfb2c2b433c0ea7ff107e33df91b18e52f960f",
|
| 1740 |
+
"is_verified": false,
|
| 1741 |
+
"line_number": 14
|
| 1742 |
+
}
|
| 1743 |
+
],
|
| 1744 |
+
"src/config/env-substitution.test.ts": [
|
| 1745 |
+
{
|
| 1746 |
+
"type": "Secret Keyword",
|
| 1747 |
+
"filename": "src/config/env-substitution.test.ts",
|
| 1748 |
+
"hashed_secret": "f2b14f68eb995facb3a1c35287b778d5bd785511",
|
| 1749 |
+
"is_verified": false,
|
| 1750 |
+
"line_number": 38
|
| 1751 |
+
},
|
| 1752 |
+
{
|
| 1753 |
+
"type": "Secret Keyword",
|
| 1754 |
+
"filename": "src/config/env-substitution.test.ts",
|
| 1755 |
+
"hashed_secret": "ec417f567082612f8fd6afafe1abcab831fca840",
|
| 1756 |
+
"is_verified": false,
|
| 1757 |
+
"line_number": 69
|
| 1758 |
+
},
|
| 1759 |
+
{
|
| 1760 |
+
"type": "Secret Keyword",
|
| 1761 |
+
"filename": "src/config/env-substitution.test.ts",
|
| 1762 |
+
"hashed_secret": "520bd69c3eb1646d9a78181ecb4c90c51fdf428d",
|
| 1763 |
+
"is_verified": false,
|
| 1764 |
+
"line_number": 70
|
| 1765 |
+
},
|
| 1766 |
+
{
|
| 1767 |
+
"type": "Secret Keyword",
|
| 1768 |
+
"filename": "src/config/env-substitution.test.ts",
|
| 1769 |
+
"hashed_secret": "f136444bf9b3d01a9f9b772b80ac6bf7b6a43ef0",
|
| 1770 |
+
"is_verified": false,
|
| 1771 |
+
"line_number": 228
|
| 1772 |
+
}
|
| 1773 |
+
],
|
| 1774 |
+
"src/config/schema.ts": [
|
| 1775 |
+
{
|
| 1776 |
+
"type": "Secret Keyword",
|
| 1777 |
+
"filename": "src/config/schema.ts",
|
| 1778 |
+
"hashed_secret": "e73c9fcad85cd4eecc74181ec4bdb31064d68439",
|
| 1779 |
+
"is_verified": false,
|
| 1780 |
+
"line_number": 184
|
| 1781 |
+
},
|
| 1782 |
+
{
|
| 1783 |
+
"type": "Secret Keyword",
|
| 1784 |
+
"filename": "src/config/schema.ts",
|
| 1785 |
+
"hashed_secret": "2eda7cd978f39eebec3bf03e4410a40e14167fff",
|
| 1786 |
+
"is_verified": false,
|
| 1787 |
+
"line_number": 220
|
| 1788 |
+
},
|
| 1789 |
+
{
|
| 1790 |
+
"type": "Secret Keyword",
|
| 1791 |
+
"filename": "src/config/schema.ts",
|
| 1792 |
+
"hashed_secret": "9f4cda226d3868676ac7f86f59e4190eb94bd208",
|
| 1793 |
+
"is_verified": false,
|
| 1794 |
+
"line_number": 418
|
| 1795 |
+
},
|
| 1796 |
+
{
|
| 1797 |
+
"type": "Secret Keyword",
|
| 1798 |
+
"filename": "src/config/schema.ts",
|
| 1799 |
+
"hashed_secret": "01822c8bbf6a8b136944b14182cb885100ec2eae",
|
| 1800 |
+
"is_verified": false,
|
| 1801 |
+
"line_number": 437
|
| 1802 |
+
},
|
| 1803 |
+
{
|
| 1804 |
+
"type": "Secret Keyword",
|
| 1805 |
+
"filename": "src/config/schema.ts",
|
| 1806 |
+
"hashed_secret": "bb7dfd9746e660e4a4374951ec5938ef0e343255",
|
| 1807 |
+
"is_verified": false,
|
| 1808 |
+
"line_number": 487
|
| 1809 |
+
}
|
| 1810 |
+
],
|
| 1811 |
+
"src/config/slack-http-config.test.ts": [
|
| 1812 |
+
{
|
| 1813 |
+
"type": "Secret Keyword",
|
| 1814 |
+
"filename": "src/config/slack-http-config.test.ts",
|
| 1815 |
+
"hashed_secret": "e5e9fa1ba31ecd1ae84f75caaa474f3a663f05f4",
|
| 1816 |
+
"is_verified": false,
|
| 1817 |
+
"line_number": 11
|
| 1818 |
+
}
|
| 1819 |
+
],
|
| 1820 |
+
"src/gateway/auth.test.ts": [
|
| 1821 |
+
{
|
| 1822 |
+
"type": "Secret Keyword",
|
| 1823 |
+
"filename": "src/gateway/auth.test.ts",
|
| 1824 |
+
"hashed_secret": "e5e9fa1ba31ecd1ae84f75caaa474f3a663f05f4",
|
| 1825 |
+
"is_verified": false,
|
| 1826 |
+
"line_number": 43
|
| 1827 |
+
},
|
| 1828 |
+
{
|
| 1829 |
+
"type": "Secret Keyword",
|
| 1830 |
+
"filename": "src/gateway/auth.test.ts",
|
| 1831 |
+
"hashed_secret": "a4b48a81cdab1e1a5dd37907d6c85ca1c61ddc7c",
|
| 1832 |
+
"is_verified": false,
|
| 1833 |
+
"line_number": 51
|
| 1834 |
+
}
|
| 1835 |
+
],
|
| 1836 |
+
"src/gateway/call.test.ts": [
|
| 1837 |
+
{
|
| 1838 |
+
"type": "Secret Keyword",
|
| 1839 |
+
"filename": "src/gateway/call.test.ts",
|
| 1840 |
+
"hashed_secret": "e5e9fa1ba31ecd1ae84f75caaa474f3a663f05f4",
|
| 1841 |
+
"is_verified": false,
|
| 1842 |
+
"line_number": 285
|
| 1843 |
+
},
|
| 1844 |
+
{
|
| 1845 |
+
"type": "Secret Keyword",
|
| 1846 |
+
"filename": "src/gateway/call.test.ts",
|
| 1847 |
+
"hashed_secret": "e493f561d90c6638c1f51c5a8a069c3b129b79ed",
|
| 1848 |
+
"is_verified": false,
|
| 1849 |
+
"line_number": 295
|
| 1850 |
+
},
|
| 1851 |
+
{
|
| 1852 |
+
"type": "Secret Keyword",
|
| 1853 |
+
"filename": "src/gateway/call.test.ts",
|
| 1854 |
+
"hashed_secret": "2e07956ffc9bc4fd624064c40b7495c85d5f1467",
|
| 1855 |
+
"is_verified": false,
|
| 1856 |
+
"line_number": 300
|
| 1857 |
+
},
|
| 1858 |
+
{
|
| 1859 |
+
"type": "Secret Keyword",
|
| 1860 |
+
"filename": "src/gateway/call.test.ts",
|
| 1861 |
+
"hashed_secret": "bddc29032de580fb53b3a9a0357dd409086db800",
|
| 1862 |
+
"is_verified": false,
|
| 1863 |
+
"line_number": 313
|
| 1864 |
+
}
|
| 1865 |
+
],
|
| 1866 |
+
"src/gateway/client.test.ts": [
|
| 1867 |
+
{
|
| 1868 |
+
"type": "Private Key",
|
| 1869 |
+
"filename": "src/gateway/client.test.ts",
|
| 1870 |
+
"hashed_secret": "1348b145fa1a555461c1b790a2f66614781091e9",
|
| 1871 |
+
"is_verified": false,
|
| 1872 |
+
"line_number": 83
|
| 1873 |
+
}
|
| 1874 |
+
],
|
| 1875 |
+
"src/gateway/gateway-cli-backend.live.test.ts": [
|
| 1876 |
+
{
|
| 1877 |
+
"type": "Hex High Entropy String",
|
| 1878 |
+
"filename": "src/gateway/gateway-cli-backend.live.test.ts",
|
| 1879 |
+
"hashed_secret": "3e2fd4a90d5afbd27974730c4d6a9592fe300825",
|
| 1880 |
+
"is_verified": false,
|
| 1881 |
+
"line_number": 38
|
| 1882 |
+
}
|
| 1883 |
+
],
|
| 1884 |
+
"src/gateway/gateway-models.profiles.live.test.ts": [
|
| 1885 |
+
{
|
| 1886 |
+
"type": "Hex High Entropy String",
|
| 1887 |
+
"filename": "src/gateway/gateway-models.profiles.live.test.ts",
|
| 1888 |
+
"hashed_secret": "3e2fd4a90d5afbd27974730c4d6a9592fe300825",
|
| 1889 |
+
"is_verified": false,
|
| 1890 |
+
"line_number": 219
|
| 1891 |
+
}
|
| 1892 |
+
],
|
| 1893 |
+
"src/gateway/gateway.e2e.test.ts": [
|
| 1894 |
+
{
|
| 1895 |
+
"type": "Secret Keyword",
|
| 1896 |
+
"filename": "src/gateway/gateway.e2e.test.ts",
|
| 1897 |
+
"hashed_secret": "a94a8fe5ccb19ba61c4c0873d391e987982fbbd3",
|
| 1898 |
+
"is_verified": false,
|
| 1899 |
+
"line_number": 73
|
| 1900 |
+
}
|
| 1901 |
+
],
|
| 1902 |
+
"src/gateway/server.auth.e2e.test.ts": [
|
| 1903 |
+
{
|
| 1904 |
+
"type": "Secret Keyword",
|
| 1905 |
+
"filename": "src/gateway/server.auth.e2e.test.ts",
|
| 1906 |
+
"hashed_secret": "e5e9fa1ba31ecd1ae84f75caaa474f3a663f05f4",
|
| 1907 |
+
"is_verified": false,
|
| 1908 |
+
"line_number": 179
|
| 1909 |
+
},
|
| 1910 |
+
{
|
| 1911 |
+
"type": "Secret Keyword",
|
| 1912 |
+
"filename": "src/gateway/server.auth.e2e.test.ts",
|
| 1913 |
+
"hashed_secret": "a4b48a81cdab1e1a5dd37907d6c85ca1c61ddc7c",
|
| 1914 |
+
"is_verified": false,
|
| 1915 |
+
"line_number": 197
|
| 1916 |
+
}
|
| 1917 |
+
],
|
| 1918 |
+
"src/gateway/session-utils.test.ts": [
|
| 1919 |
+
{
|
| 1920 |
+
"type": "Base64 High Entropy String",
|
| 1921 |
+
"filename": "src/gateway/session-utils.test.ts",
|
| 1922 |
+
"hashed_secret": "bb9a5d9483409d2c60b28268a0efcb93324d4cda",
|
| 1923 |
+
"is_verified": false,
|
| 1924 |
+
"line_number": 156
|
| 1925 |
+
}
|
| 1926 |
+
],
|
| 1927 |
+
"src/gateway/tools-invoke-http.test.ts": [
|
| 1928 |
+
{
|
| 1929 |
+
"type": "Secret Keyword",
|
| 1930 |
+
"filename": "src/gateway/tools-invoke-http.test.ts",
|
| 1931 |
+
"hashed_secret": "e5e9fa1ba31ecd1ae84f75caaa474f3a663f05f4",
|
| 1932 |
+
"is_verified": false,
|
| 1933 |
+
"line_number": 56
|
| 1934 |
+
}
|
| 1935 |
+
],
|
| 1936 |
+
"src/gateway/ws-log.test.ts": [
|
| 1937 |
+
{
|
| 1938 |
+
"type": "Base64 High Entropy String",
|
| 1939 |
+
"filename": "src/gateway/ws-log.test.ts",
|
| 1940 |
+
"hashed_secret": "edd2e7ac4f61d0c606e80a0919d727540842a307",
|
| 1941 |
+
"is_verified": false,
|
| 1942 |
+
"line_number": 22
|
| 1943 |
+
}
|
| 1944 |
+
],
|
| 1945 |
+
"src/infra/env.test.ts": [
|
| 1946 |
+
{
|
| 1947 |
+
"type": "Secret Keyword",
|
| 1948 |
+
"filename": "src/infra/env.test.ts",
|
| 1949 |
+
"hashed_secret": "df98a117ddabf85991b9fe0e268214dc0e1254dc",
|
| 1950 |
+
"is_verified": false,
|
| 1951 |
+
"line_number": 10
|
| 1952 |
+
},
|
| 1953 |
+
{
|
| 1954 |
+
"type": "Secret Keyword",
|
| 1955 |
+
"filename": "src/infra/env.test.ts",
|
| 1956 |
+
"hashed_secret": "6d811dc1f59a55ca1a3d38b5042a062b9f79e8ec",
|
| 1957 |
+
"is_verified": false,
|
| 1958 |
+
"line_number": 25
|
| 1959 |
+
}
|
| 1960 |
+
],
|
| 1961 |
+
"src/infra/outbound/message-action-runner.test.ts": [
|
| 1962 |
+
{
|
| 1963 |
+
"type": "Hex High Entropy String",
|
| 1964 |
+
"filename": "src/infra/outbound/message-action-runner.test.ts",
|
| 1965 |
+
"hashed_secret": "804ec071803318791b835cffd6e509c8d32239db",
|
| 1966 |
+
"is_verified": false,
|
| 1967 |
+
"line_number": 88
|
| 1968 |
+
},
|
| 1969 |
+
{
|
| 1970 |
+
"type": "Secret Keyword",
|
| 1971 |
+
"filename": "src/infra/outbound/message-action-runner.test.ts",
|
| 1972 |
+
"hashed_secret": "789cbe0407840b1c2041cb33452ff60f19bf58cc",
|
| 1973 |
+
"is_verified": false,
|
| 1974 |
+
"line_number": 385
|
| 1975 |
+
}
|
| 1976 |
+
],
|
| 1977 |
+
"src/infra/outbound/outbound-policy.test.ts": [
|
| 1978 |
+
{
|
| 1979 |
+
"type": "Hex High Entropy String",
|
| 1980 |
+
"filename": "src/infra/outbound/outbound-policy.test.ts",
|
| 1981 |
+
"hashed_secret": "804ec071803318791b835cffd6e509c8d32239db",
|
| 1982 |
+
"is_verified": false,
|
| 1983 |
+
"line_number": 33
|
| 1984 |
+
}
|
| 1985 |
+
],
|
| 1986 |
+
"src/infra/shell-env.test.ts": [
|
| 1987 |
+
{
|
| 1988 |
+
"type": "Secret Keyword",
|
| 1989 |
+
"filename": "src/infra/shell-env.test.ts",
|
| 1990 |
+
"hashed_secret": "65c10dc3549fe07424148a8a4790a3341ecbc253",
|
| 1991 |
+
"is_verified": false,
|
| 1992 |
+
"line_number": 27
|
| 1993 |
+
},
|
| 1994 |
+
{
|
| 1995 |
+
"type": "Secret Keyword",
|
| 1996 |
+
"filename": "src/infra/shell-env.test.ts",
|
| 1997 |
+
"hashed_secret": "e013ffda590d2178607c16d11b1ea42f75ceb0e7",
|
| 1998 |
+
"is_verified": false,
|
| 1999 |
+
"line_number": 59
|
| 2000 |
+
},
|
| 2001 |
+
{
|
| 2002 |
+
"type": "Base64 High Entropy String",
|
| 2003 |
+
"filename": "src/infra/shell-env.test.ts",
|
| 2004 |
+
"hashed_secret": "be6ee9a6bf9f2dad84a5a67d6c0576a5bacc391e",
|
| 2005 |
+
"is_verified": false,
|
| 2006 |
+
"line_number": 61
|
| 2007 |
+
}
|
| 2008 |
+
],
|
| 2009 |
+
"src/logging/redact.test.ts": [
|
| 2010 |
+
{
|
| 2011 |
+
"type": "Base64 High Entropy String",
|
| 2012 |
+
"filename": "src/logging/redact.test.ts",
|
| 2013 |
+
"hashed_secret": "dd7754662b89333191ff45e8257a3e6d3fcd3990",
|
| 2014 |
+
"is_verified": false,
|
| 2015 |
+
"line_number": 9
|
| 2016 |
+
},
|
| 2017 |
+
{
|
| 2018 |
+
"type": "Private Key",
|
| 2019 |
+
"filename": "src/logging/redact.test.ts",
|
| 2020 |
+
"hashed_secret": "1348b145fa1a555461c1b790a2f66614781091e9",
|
| 2021 |
+
"is_verified": false,
|
| 2022 |
+
"line_number": 64
|
| 2023 |
+
},
|
| 2024 |
+
{
|
| 2025 |
+
"type": "Hex High Entropy String",
|
| 2026 |
+
"filename": "src/logging/redact.test.ts",
|
| 2027 |
+
"hashed_secret": "7992945213f7d76889fa83ff0f2be352409c837e",
|
| 2028 |
+
"is_verified": false,
|
| 2029 |
+
"line_number": 65
|
| 2030 |
+
},
|
| 2031 |
+
{
|
| 2032 |
+
"type": "Base64 High Entropy String",
|
| 2033 |
+
"filename": "src/logging/redact.test.ts",
|
| 2034 |
+
"hashed_secret": "063995ecb4fa5afe2460397d322925cd867b7d74",
|
| 2035 |
+
"is_verified": false,
|
| 2036 |
+
"line_number": 79
|
| 2037 |
+
}
|
| 2038 |
+
],
|
| 2039 |
+
"src/media-understanding/apply.test.ts": [
|
| 2040 |
+
{
|
| 2041 |
+
"type": "Secret Keyword",
|
| 2042 |
+
"filename": "src/media-understanding/apply.test.ts",
|
| 2043 |
+
"hashed_secret": "3acfb2c2b433c0ea7ff107e33df91b18e52f960f",
|
| 2044 |
+
"is_verified": false,
|
| 2045 |
+
"line_number": 14
|
| 2046 |
+
}
|
| 2047 |
+
],
|
| 2048 |
+
"src/media-understanding/providers/deepgram/audio.test.ts": [
|
| 2049 |
+
{
|
| 2050 |
+
"type": "Secret Keyword",
|
| 2051 |
+
"filename": "src/media-understanding/providers/deepgram/audio.test.ts",
|
| 2052 |
+
"hashed_secret": "3acfb2c2b433c0ea7ff107e33df91b18e52f960f",
|
| 2053 |
+
"is_verified": false,
|
| 2054 |
+
"line_number": 31
|
| 2055 |
+
}
|
| 2056 |
+
],
|
| 2057 |
+
"src/media-understanding/providers/google/video.test.ts": [
|
| 2058 |
+
{
|
| 2059 |
+
"type": "Secret Keyword",
|
| 2060 |
+
"filename": "src/media-understanding/providers/google/video.test.ts",
|
| 2061 |
+
"hashed_secret": "3acfb2c2b433c0ea7ff107e33df91b18e52f960f",
|
| 2062 |
+
"is_verified": false,
|
| 2063 |
+
"line_number": 28
|
| 2064 |
+
}
|
| 2065 |
+
],
|
| 2066 |
+
"src/media-understanding/providers/openai/audio.test.ts": [
|
| 2067 |
+
{
|
| 2068 |
+
"type": "Secret Keyword",
|
| 2069 |
+
"filename": "src/media-understanding/providers/openai/audio.test.ts",
|
| 2070 |
+
"hashed_secret": "3acfb2c2b433c0ea7ff107e33df91b18e52f960f",
|
| 2071 |
+
"is_verified": false,
|
| 2072 |
+
"line_number": 26
|
| 2073 |
+
}
|
| 2074 |
+
],
|
| 2075 |
+
"src/media-understanding/runner.auto-audio.test.ts": [
|
| 2076 |
+
{
|
| 2077 |
+
"type": "Secret Keyword",
|
| 2078 |
+
"filename": "src/media-understanding/runner.auto-audio.test.ts",
|
| 2079 |
+
"hashed_secret": "3acfb2c2b433c0ea7ff107e33df91b18e52f960f",
|
| 2080 |
+
"is_verified": false,
|
| 2081 |
+
"line_number": 42
|
| 2082 |
+
}
|
| 2083 |
+
],
|
| 2084 |
+
"src/media-understanding/runner.deepgram.test.ts": [
|
| 2085 |
+
{
|
| 2086 |
+
"type": "Secret Keyword",
|
| 2087 |
+
"filename": "src/media-understanding/runner.deepgram.test.ts",
|
| 2088 |
+
"hashed_secret": "3acfb2c2b433c0ea7ff107e33df91b18e52f960f",
|
| 2089 |
+
"is_verified": false,
|
| 2090 |
+
"line_number": 46
|
| 2091 |
+
}
|
| 2092 |
+
],
|
| 2093 |
+
"src/memory/embeddings.test.ts": [
|
| 2094 |
+
{
|
| 2095 |
+
"type": "Secret Keyword",
|
| 2096 |
+
"filename": "src/memory/embeddings.test.ts",
|
| 2097 |
+
"hashed_secret": "a47110e348a3063541fb1f1f640d635d457181a0",
|
| 2098 |
+
"is_verified": false,
|
| 2099 |
+
"line_number": 32
|
| 2100 |
+
},
|
| 2101 |
+
{
|
| 2102 |
+
"type": "Secret Keyword",
|
| 2103 |
+
"filename": "src/memory/embeddings.test.ts",
|
| 2104 |
+
"hashed_secret": "c734e47630dda71619c696d88381f06f7511bd78",
|
| 2105 |
+
"is_verified": false,
|
| 2106 |
+
"line_number": 149
|
| 2107 |
+
},
|
| 2108 |
+
{
|
| 2109 |
+
"type": "Secret Keyword",
|
| 2110 |
+
"filename": "src/memory/embeddings.test.ts",
|
| 2111 |
+
"hashed_secret": "56e1d57b8db262b08bc73c60ed08d8c92e59503f",
|
| 2112 |
+
"is_verified": false,
|
| 2113 |
+
"line_number": 179
|
| 2114 |
+
}
|
| 2115 |
+
],
|
| 2116 |
+
"src/pairing/pairing-store.ts": [
|
| 2117 |
+
{
|
| 2118 |
+
"type": "Base64 High Entropy String",
|
| 2119 |
+
"filename": "src/pairing/pairing-store.ts",
|
| 2120 |
+
"hashed_secret": "f8c6f1ff98c5ee78c27d34a3ca68f35ad79847af",
|
| 2121 |
+
"is_verified": false,
|
| 2122 |
+
"line_number": 12
|
| 2123 |
+
}
|
| 2124 |
+
],
|
| 2125 |
+
"src/security/audit.test.ts": [
|
| 2126 |
+
{
|
| 2127 |
+
"type": "Hex High Entropy String",
|
| 2128 |
+
"filename": "src/security/audit.test.ts",
|
| 2129 |
+
"hashed_secret": "b1775a785f09a6ebaf2dc33d6eaeb98974d9cdb8",
|
| 2130 |
+
"is_verified": false,
|
| 2131 |
+
"line_number": 180
|
| 2132 |
+
},
|
| 2133 |
+
{
|
| 2134 |
+
"type": "Hex High Entropy String",
|
| 2135 |
+
"filename": "src/security/audit.test.ts",
|
| 2136 |
+
"hashed_secret": "fa8da98a5bdb77b4902cbb4338e6e94ea825300e",
|
| 2137 |
+
"is_verified": false,
|
| 2138 |
+
"line_number": 209
|
| 2139 |
+
},
|
| 2140 |
+
{
|
| 2141 |
+
"type": "Secret Keyword",
|
| 2142 |
+
"filename": "src/security/audit.test.ts",
|
| 2143 |
+
"hashed_secret": "21f688ab56f76a99e5c6ed342291422f4e57e47f",
|
| 2144 |
+
"is_verified": false,
|
| 2145 |
+
"line_number": 1046
|
| 2146 |
+
},
|
| 2147 |
+
{
|
| 2148 |
+
"type": "Secret Keyword",
|
| 2149 |
+
"filename": "src/security/audit.test.ts",
|
| 2150 |
+
"hashed_secret": "3dc927d80543dc0f643940b70d066bd4b4c4b78e",
|
| 2151 |
+
"is_verified": false,
|
| 2152 |
+
"line_number": 1077
|
| 2153 |
+
}
|
| 2154 |
+
],
|
| 2155 |
+
"src/tts/tts.test.ts": [
|
| 2156 |
+
{
|
| 2157 |
+
"type": "Secret Keyword",
|
| 2158 |
+
"filename": "src/tts/tts.test.ts",
|
| 2159 |
+
"hashed_secret": "2e7a7ee14caebf378fc32d6cf6f557f347c96773",
|
| 2160 |
+
"is_verified": false,
|
| 2161 |
+
"line_number": 33
|
| 2162 |
+
},
|
| 2163 |
+
{
|
| 2164 |
+
"type": "Hex High Entropy String",
|
| 2165 |
+
"filename": "src/tts/tts.test.ts",
|
| 2166 |
+
"hashed_secret": "b214f706bb602c1cc2adc5c6165e73622305f4bb",
|
| 2167 |
+
"is_verified": false,
|
| 2168 |
+
"line_number": 68
|
| 2169 |
+
}
|
| 2170 |
+
],
|
| 2171 |
+
"src/web/qr-image.test.ts": [
|
| 2172 |
+
{
|
| 2173 |
+
"type": "Hex High Entropy String",
|
| 2174 |
+
"filename": "src/web/qr-image.test.ts",
|
| 2175 |
+
"hashed_secret": "564666dc1ca6e7318b2d5feeb1ce7b5bf717411e",
|
| 2176 |
+
"is_verified": false,
|
| 2177 |
+
"line_number": 12
|
| 2178 |
+
}
|
| 2179 |
+
],
|
| 2180 |
+
"test/provider-timeout.e2e.test.ts": [
|
| 2181 |
+
{
|
| 2182 |
+
"type": "Secret Keyword",
|
| 2183 |
+
"filename": "test/provider-timeout.e2e.test.ts",
|
| 2184 |
+
"hashed_secret": "a94a8fe5ccb19ba61c4c0873d391e987982fbbd3",
|
| 2185 |
+
"is_verified": false,
|
| 2186 |
+
"line_number": 182
|
| 2187 |
+
}
|
| 2188 |
+
]
|
| 2189 |
+
},
|
| 2190 |
+
"generated_at": "2026-01-25T10:55:04Z"
|
| 2191 |
+
}
|
.shellcheckrc
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# ShellCheck configuration
|
| 2 |
+
# https://www.shellcheck.net/wiki/
|
| 3 |
+
|
| 4 |
+
# Disable common false positives and style suggestions
|
| 5 |
+
|
| 6 |
+
# SC2034: Variable appears unused (often exported or used indirectly)
|
| 7 |
+
disable=SC2034
|
| 8 |
+
|
| 9 |
+
# SC2155: Declare and assign separately (common idiom, rarely causes issues)
|
| 10 |
+
disable=SC2155
|
| 11 |
+
|
| 12 |
+
# SC2295: Expansions inside ${..} need quoting (info-level, rarely causes issues)
|
| 13 |
+
disable=SC2295
|
| 14 |
+
|
| 15 |
+
# SC1012: \r is literal (tr -d '\r' works as intended on most systems)
|
| 16 |
+
disable=SC1012
|
| 17 |
+
|
| 18 |
+
# SC2026: Word outside quotes (info-level, often intentional)
|
| 19 |
+
disable=SC2026
|
| 20 |
+
|
| 21 |
+
# SC2016: Expressions don't expand in single quotes (often intentional in sed/awk)
|
| 22 |
+
disable=SC2016
|
| 23 |
+
|
| 24 |
+
# SC2129: Consider using { cmd1; cmd2; } >> file (style preference)
|
| 25 |
+
disable=SC2129
|
.swiftformat
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# SwiftFormat configuration adapted from Peekaboo defaults (Swift 6 friendly)
|
| 2 |
+
|
| 3 |
+
--swiftversion 6.2
|
| 4 |
+
|
| 5 |
+
# Self handling
|
| 6 |
+
--self insert
|
| 7 |
+
--selfrequired
|
| 8 |
+
|
| 9 |
+
# Imports / extensions
|
| 10 |
+
--importgrouping testable-bottom
|
| 11 |
+
--extensionacl on-declarations
|
| 12 |
+
|
| 13 |
+
# Indentation
|
| 14 |
+
--indent 4
|
| 15 |
+
--indentcase false
|
| 16 |
+
--ifdef no-indent
|
| 17 |
+
--xcodeindentation enabled
|
| 18 |
+
|
| 19 |
+
# Line breaks
|
| 20 |
+
--linebreaks lf
|
| 21 |
+
--maxwidth 120
|
| 22 |
+
|
| 23 |
+
# Whitespace
|
| 24 |
+
--trimwhitespace always
|
| 25 |
+
--emptybraces no-space
|
| 26 |
+
--nospaceoperators ...,..<
|
| 27 |
+
--ranges no-space
|
| 28 |
+
--someAny true
|
| 29 |
+
--voidtype void
|
| 30 |
+
|
| 31 |
+
# Wrapping
|
| 32 |
+
--wraparguments before-first
|
| 33 |
+
--wrapparameters before-first
|
| 34 |
+
--wrapcollections before-first
|
| 35 |
+
--closingparen same-line
|
| 36 |
+
|
| 37 |
+
# Organization
|
| 38 |
+
--organizetypes class,struct,enum,extension
|
| 39 |
+
--extensionmark "MARK: - %t + %p"
|
| 40 |
+
--marktypes always
|
| 41 |
+
--markextensions always
|
| 42 |
+
--structthreshold 0
|
| 43 |
+
--enumthreshold 0
|
| 44 |
+
|
| 45 |
+
# Other
|
| 46 |
+
--stripunusedargs closure-only
|
| 47 |
+
--header ignore
|
| 48 |
+
--allman false
|
| 49 |
+
|
| 50 |
+
# Exclusions
|
| 51 |
+
--exclude .build,.swiftpm,DerivedData,node_modules,dist,coverage,xcuserdata,Peekaboo,Swabble,apps/android,apps/ios,apps/shared,apps/macos/Sources/ClawdisProtocol,apps/macos/Sources/ClawdbotProtocol
|
.swiftlint.yml
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# SwiftLint configuration adapted from Peekaboo defaults (Swift 6 friendly)
|
| 2 |
+
|
| 3 |
+
included:
|
| 4 |
+
- apps/macos/Sources
|
| 5 |
+
|
| 6 |
+
excluded:
|
| 7 |
+
- .build
|
| 8 |
+
- DerivedData
|
| 9 |
+
- "**/.build"
|
| 10 |
+
- "**/.swiftpm"
|
| 11 |
+
- "**/DerivedData"
|
| 12 |
+
- "**/Generated"
|
| 13 |
+
- "**/Resources"
|
| 14 |
+
- "**/Package.swift"
|
| 15 |
+
- "**/Tests/Resources"
|
| 16 |
+
- node_modules
|
| 17 |
+
- dist
|
| 18 |
+
- coverage
|
| 19 |
+
- "*.playground"
|
| 20 |
+
# Generated (protocol-gen-swift.ts)
|
| 21 |
+
- apps/macos/Sources/ClawdbotProtocol/GatewayModels.swift
|
| 22 |
+
|
| 23 |
+
analyzer_rules:
|
| 24 |
+
- unused_declaration
|
| 25 |
+
- unused_import
|
| 26 |
+
|
| 27 |
+
opt_in_rules:
|
| 28 |
+
- array_init
|
| 29 |
+
- closure_spacing
|
| 30 |
+
- contains_over_first_not_nil
|
| 31 |
+
- empty_count
|
| 32 |
+
- empty_string
|
| 33 |
+
- explicit_init
|
| 34 |
+
- fallthrough
|
| 35 |
+
- fatal_error_message
|
| 36 |
+
- first_where
|
| 37 |
+
- joined_default_parameter
|
| 38 |
+
- last_where
|
| 39 |
+
- literal_expression_end_indentation
|
| 40 |
+
- multiline_arguments
|
| 41 |
+
- multiline_parameters
|
| 42 |
+
- operator_usage_whitespace
|
| 43 |
+
- overridden_super_call
|
| 44 |
+
- pattern_matching_keywords
|
| 45 |
+
- private_outlet
|
| 46 |
+
- prohibited_super_call
|
| 47 |
+
- redundant_nil_coalescing
|
| 48 |
+
- sorted_first_last
|
| 49 |
+
- switch_case_alignment
|
| 50 |
+
- unneeded_parentheses_in_closure_argument
|
| 51 |
+
- vertical_parameter_alignment_on_call
|
| 52 |
+
|
| 53 |
+
disabled_rules:
|
| 54 |
+
# SwiftFormat handles these
|
| 55 |
+
- trailing_whitespace
|
| 56 |
+
- trailing_newline
|
| 57 |
+
- trailing_comma
|
| 58 |
+
- vertical_whitespace
|
| 59 |
+
- indentation_width
|
| 60 |
+
|
| 61 |
+
# Style exclusions
|
| 62 |
+
- explicit_self
|
| 63 |
+
- identifier_name
|
| 64 |
+
- file_header
|
| 65 |
+
- explicit_top_level_acl
|
| 66 |
+
- explicit_acl
|
| 67 |
+
- explicit_type_interface
|
| 68 |
+
- missing_docs
|
| 69 |
+
- required_deinit
|
| 70 |
+
- prefer_nimble
|
| 71 |
+
- quick_discouraged_call
|
| 72 |
+
- quick_discouraged_focused_test
|
| 73 |
+
- quick_discouraged_pending_test
|
| 74 |
+
- anonymous_argument_in_multiline_closure
|
| 75 |
+
- no_extension_access_modifier
|
| 76 |
+
- no_grouping_extension
|
| 77 |
+
- switch_case_on_newline
|
| 78 |
+
- strict_fileprivate
|
| 79 |
+
- extension_access_modifier
|
| 80 |
+
- convenience_type
|
| 81 |
+
- no_magic_numbers
|
| 82 |
+
- one_declaration_per_file
|
| 83 |
+
- vertical_whitespace_between_cases
|
| 84 |
+
- vertical_whitespace_closing_braces
|
| 85 |
+
- superfluous_else
|
| 86 |
+
- number_separator
|
| 87 |
+
- prefixed_toplevel_constant
|
| 88 |
+
- opening_brace
|
| 89 |
+
- trailing_closure
|
| 90 |
+
- contrasted_opening_brace
|
| 91 |
+
- sorted_imports
|
| 92 |
+
- redundant_type_annotation
|
| 93 |
+
- shorthand_optional_binding
|
| 94 |
+
- untyped_error_in_catch
|
| 95 |
+
- file_name
|
| 96 |
+
- todo
|
| 97 |
+
|
| 98 |
+
force_cast: warning
|
| 99 |
+
force_try: warning
|
| 100 |
+
|
| 101 |
+
type_name:
|
| 102 |
+
min_length:
|
| 103 |
+
warning: 2
|
| 104 |
+
error: 1
|
| 105 |
+
max_length:
|
| 106 |
+
warning: 60
|
| 107 |
+
error: 80
|
| 108 |
+
|
| 109 |
+
function_body_length:
|
| 110 |
+
warning: 150
|
| 111 |
+
error: 300
|
| 112 |
+
|
| 113 |
+
function_parameter_count:
|
| 114 |
+
warning: 7
|
| 115 |
+
error: 10
|
| 116 |
+
|
| 117 |
+
file_length:
|
| 118 |
+
warning: 1500
|
| 119 |
+
error: 2500
|
| 120 |
+
ignore_comment_only_lines: true
|
| 121 |
+
|
| 122 |
+
type_body_length:
|
| 123 |
+
warning: 800
|
| 124 |
+
error: 1200
|
| 125 |
+
|
| 126 |
+
cyclomatic_complexity:
|
| 127 |
+
warning: 20
|
| 128 |
+
error: 120
|
| 129 |
+
|
| 130 |
+
large_tuple:
|
| 131 |
+
warning: 4
|
| 132 |
+
error: 5
|
| 133 |
+
|
| 134 |
+
nesting:
|
| 135 |
+
type_level:
|
| 136 |
+
warning: 4
|
| 137 |
+
error: 6
|
| 138 |
+
function_level:
|
| 139 |
+
warning: 5
|
| 140 |
+
error: 7
|
| 141 |
+
|
| 142 |
+
line_length:
|
| 143 |
+
warning: 120
|
| 144 |
+
error: 250
|
| 145 |
+
ignores_comments: true
|
| 146 |
+
ignores_urls: true
|
| 147 |
+
|
| 148 |
+
reporter: "xcode"
|
AGENTS.md
ADDED
|
@@ -0,0 +1,163 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Repository Guidelines
|
| 2 |
+
- Repo: https://github.com/moltbot/moltbot
|
| 3 |
+
- GitHub issues/comments/PR comments: use literal multiline strings or `-F - <<'EOF'` (or $'...') for real newlines; never embed "\\n".
|
| 4 |
+
|
| 5 |
+
## Project Structure & Module Organization
|
| 6 |
+
- Source code: `src/` (CLI wiring in `src/cli`, commands in `src/commands`, web provider in `src/provider-web.ts`, infra in `src/infra`, media pipeline in `src/media`).
|
| 7 |
+
- Tests: colocated `*.test.ts`.
|
| 8 |
+
- Docs: `docs/` (images, queue, Pi config). Built output lives in `dist/`.
|
| 9 |
+
- Plugins/extensions: live under `extensions/*` (workspace packages). Keep plugin-only deps in the extension `package.json`; do not add them to the root `package.json` unless core uses them.
|
| 10 |
+
- Plugins: install runs `npm install --omit=dev` in plugin dir; runtime deps must live in `dependencies`. Avoid `workspace:*` in `dependencies` (npm install breaks); put `moltbot` in `devDependencies` or `peerDependencies` instead (runtime resolves `clawdbot/plugin-sdk` via jiti alias).
|
| 11 |
+
- Installers served from `https://molt.bot/*`: live in the sibling repo `../molt.bot` (`public/install.sh`, `public/install-cli.sh`, `public/install.ps1`).
|
| 12 |
+
- Messaging channels: always consider **all** built-in + extension channels when refactoring shared logic (routing, allowlists, pairing, command gating, onboarding, docs).
|
| 13 |
+
- Core channel docs: `docs/channels/`
|
| 14 |
+
- Core channel code: `src/telegram`, `src/discord`, `src/slack`, `src/signal`, `src/imessage`, `src/web` (WhatsApp web), `src/channels`, `src/routing`
|
| 15 |
+
- Extensions (channel plugins): `extensions/*` (e.g. `extensions/msteams`, `extensions/matrix`, `extensions/zalo`, `extensions/zalouser`, `extensions/voice-call`)
|
| 16 |
+
- When adding channels/extensions/apps/docs, review `.github/labeler.yml` for label coverage.
|
| 17 |
+
|
| 18 |
+
## Docs Linking (Mintlify)
|
| 19 |
+
- Docs are hosted on Mintlify (docs.molt.bot).
|
| 20 |
+
- Internal doc links in `docs/**/*.md`: root-relative, no `.md`/`.mdx` (example: `[Config](/configuration)`).
|
| 21 |
+
- Section cross-references: use anchors on root-relative paths (example: `[Hooks](/configuration#hooks)`).
|
| 22 |
+
- Doc headings and anchors: avoid em dashes and apostrophes in headings because they break Mintlify anchor links.
|
| 23 |
+
- When Peter asks for links, reply with full `https://docs.molt.bot/...` URLs (not root-relative).
|
| 24 |
+
- When you touch docs, end the reply with the `https://docs.molt.bot/...` URLs you referenced.
|
| 25 |
+
- README (GitHub): keep absolute docs URLs (`https://docs.molt.bot/...`) so links work on GitHub.
|
| 26 |
+
- Docs content must be generic: no personal device names/hostnames/paths; use placeholders like `user@gateway-host` and “gateway host”.
|
| 27 |
+
|
| 28 |
+
## exe.dev VM ops (general)
|
| 29 |
+
- Access: stable path is `ssh exe.dev` then `ssh vm-name` (assume SSH key already set).
|
| 30 |
+
- SSH flaky: use exe.dev web terminal or Shelley (web agent); keep a tmux session for long ops.
|
| 31 |
+
- Update: `sudo npm i -g moltbot@latest` (global install needs root on `/usr/lib/node_modules`).
|
| 32 |
+
- Config: use `moltbot config set ...`; ensure `gateway.mode=local` is set.
|
| 33 |
+
- Discord: store raw token only (no `DISCORD_BOT_TOKEN=` prefix).
|
| 34 |
+
- Restart: stop old gateway and run:
|
| 35 |
+
`pkill -9 -f moltbot-gateway || true; nohup moltbot gateway run --bind loopback --port 18789 --force > /tmp/moltbot-gateway.log 2>&1 &`
|
| 36 |
+
- Verify: `moltbot channels status --probe`, `ss -ltnp | rg 18789`, `tail -n 120 /tmp/moltbot-gateway.log`.
|
| 37 |
+
|
| 38 |
+
## Build, Test, and Development Commands
|
| 39 |
+
- Runtime baseline: Node **22+** (keep Node + Bun paths working).
|
| 40 |
+
- Install deps: `pnpm install`
|
| 41 |
+
- Pre-commit hooks: `prek install` (runs same checks as CI)
|
| 42 |
+
- Also supported: `bun install` (keep `pnpm-lock.yaml` + Bun patching in sync when touching deps/patches).
|
| 43 |
+
- Prefer Bun for TypeScript execution (scripts, dev, tests): `bun <file.ts>` / `bunx <tool>`.
|
| 44 |
+
- Run CLI in dev: `pnpm moltbot ...` (bun) or `pnpm dev`.
|
| 45 |
+
- Node remains supported for running built output (`dist/*`) and production installs.
|
| 46 |
+
- Mac packaging (dev): `scripts/package-mac-app.sh` defaults to current arch. Release checklist: `docs/platforms/mac/release.md`.
|
| 47 |
+
- Type-check/build: `pnpm build` (tsc)
|
| 48 |
+
- Lint/format: `pnpm lint` (oxlint), `pnpm format` (oxfmt)
|
| 49 |
+
- Tests: `pnpm test` (vitest); coverage: `pnpm test:coverage`
|
| 50 |
+
|
| 51 |
+
## Coding Style & Naming Conventions
|
| 52 |
+
- Language: TypeScript (ESM). Prefer strict typing; avoid `any`.
|
| 53 |
+
- Formatting/linting via Oxlint and Oxfmt; run `pnpm lint` before commits.
|
| 54 |
+
- Add brief code comments for tricky or non-obvious logic.
|
| 55 |
+
- Keep files concise; extract helpers instead of “V2” copies. Use existing patterns for CLI options and dependency injection via `createDefaultDeps`.
|
| 56 |
+
- Aim to keep files under ~700 LOC; guideline only (not a hard guardrail). Split/refactor when it improves clarity or testability.
|
| 57 |
+
- Naming: use **Moltbot** for product/app/docs headings; use `moltbot` for CLI command, package/binary, paths, and config keys.
|
| 58 |
+
|
| 59 |
+
## Release Channels (Naming)
|
| 60 |
+
- stable: tagged releases only (e.g. `vYYYY.M.D`), npm dist-tag `latest`.
|
| 61 |
+
- beta: prerelease tags `vYYYY.M.D-beta.N`, npm dist-tag `beta` (may ship without macOS app).
|
| 62 |
+
- dev: moving head on `main` (no tag; git checkout main).
|
| 63 |
+
|
| 64 |
+
## Testing Guidelines
|
| 65 |
+
- Framework: Vitest with V8 coverage thresholds (70% lines/branches/functions/statements).
|
| 66 |
+
- Naming: match source names with `*.test.ts`; e2e in `*.e2e.test.ts`.
|
| 67 |
+
- Run `pnpm test` (or `pnpm test:coverage`) before pushing when you touch logic.
|
| 68 |
+
- Do not set test workers above 16; tried already.
|
| 69 |
+
- Live tests (real keys): `CLAWDBOT_LIVE_TEST=1 pnpm test:live` (Moltbot-only) or `LIVE=1 pnpm test:live` (includes provider live tests). Docker: `pnpm test:docker:live-models`, `pnpm test:docker:live-gateway`. Onboarding Docker E2E: `pnpm test:docker:onboard`.
|
| 70 |
+
- Full kit + what’s covered: `docs/testing.md`.
|
| 71 |
+
- Pure test additions/fixes generally do **not** need a changelog entry unless they alter user-facing behavior or the user asks for one.
|
| 72 |
+
- Mobile: before using a simulator, check for connected real devices (iOS + Android) and prefer them when available.
|
| 73 |
+
|
| 74 |
+
## Commit & Pull Request Guidelines
|
| 75 |
+
- Create commits with `scripts/committer "<msg>" <file...>`; avoid manual `git add`/`git commit` so staging stays scoped.
|
| 76 |
+
- Follow concise, action-oriented commit messages (e.g., `CLI: add verbose flag to send`).
|
| 77 |
+
- Group related changes; avoid bundling unrelated refactors.
|
| 78 |
+
- Changelog workflow: keep latest released version at top (no `Unreleased`); after publishing, bump version and start a new top section.
|
| 79 |
+
- PRs should summarize scope, note testing performed, and mention any user-facing changes or new flags.
|
| 80 |
+
- PR review flow: when given a PR link, review via `gh pr view`/`gh pr diff` and do **not** change branches.
|
| 81 |
+
- PR review calls: prefer a single `gh pr view --json ...` to batch metadata/comments; run `gh pr diff` only when needed.
|
| 82 |
+
- Before starting a review when a GH Issue/PR is pasted: run `git pull`; if there are local changes or unpushed commits, stop and alert the user before reviewing.
|
| 83 |
+
- Goal: merge PRs. Prefer **rebase** when commits are clean; **squash** when history is messy.
|
| 84 |
+
- PR merge flow: create a temp branch from `main`, merge the PR branch into it (prefer squash unless commit history is important; use rebase/merge when it is). Always try to merge the PR unless it’s truly difficult, then use another approach. If we squash, add the PR author as a co-contributor. Apply fixes, add changelog entry (include PR # + thanks), run full gate before the final commit, commit, merge back to `main`, delete the temp branch, and end on `main`.
|
| 85 |
+
- If you review a PR and later do work on it, land via merge/squash (no direct-main commits) and always add the PR author as a co-contributor.
|
| 86 |
+
- When working on a PR: add a changelog entry with the PR number and thank the contributor.
|
| 87 |
+
- When working on an issue: reference the issue in the changelog entry.
|
| 88 |
+
- When merging a PR: leave a PR comment that explains exactly what we did and include the SHA hashes.
|
| 89 |
+
- When merging a PR from a new contributor: add their avatar to the README “Thanks to all clawtributors” thumbnail list.
|
| 90 |
+
- After merging a PR: run `bun scripts/update-clawtributors.ts` if the contributor is missing, then commit the regenerated README.
|
| 91 |
+
|
| 92 |
+
## Shorthand Commands
|
| 93 |
+
- `sync`: if working tree is dirty, commit all changes (pick a sensible Conventional Commit message), then `git pull --rebase`; if rebase conflicts and cannot resolve, stop; otherwise `git push`.
|
| 94 |
+
|
| 95 |
+
### PR Workflow (Review vs Land)
|
| 96 |
+
- **Review mode (PR link only):** read `gh pr view/diff`; **do not** switch branches; **do not** change code.
|
| 97 |
+
- **Landing mode:** create an integration branch from `main`, bring in PR commits (**prefer rebase** for linear history; **merge allowed** when complexity/conflicts make it safer), apply fixes, add changelog (+ thanks + PR #), run full gate **locally before committing** (`pnpm lint && pnpm build && pnpm test`), commit, merge back to `main`, then `git switch main` (never stay on a topic branch after landing). Important: contributor needs to be in git graph after this!
|
| 98 |
+
|
| 99 |
+
## Security & Configuration Tips
|
| 100 |
+
- Web provider stores creds at `~/.clawdbot/credentials/`; rerun `moltbot login` if logged out.
|
| 101 |
+
- Pi sessions live under `~/.clawdbot/sessions/` by default; the base directory is not configurable.
|
| 102 |
+
- Environment variables: see `~/.profile`.
|
| 103 |
+
- Never commit or publish real phone numbers, videos, or live configuration values. Use obviously fake placeholders in docs, tests, and examples.
|
| 104 |
+
- Release flow: always read `docs/reference/RELEASING.md` and `docs/platforms/mac/release.md` before any release work; do not ask routine questions once those docs answer them.
|
| 105 |
+
|
| 106 |
+
## Troubleshooting
|
| 107 |
+
- Rebrand/migration issues or legacy config/service warnings: run `moltbot doctor` (see `docs/gateway/doctor.md`).
|
| 108 |
+
|
| 109 |
+
## Agent-Specific Notes
|
| 110 |
+
- Vocabulary: "makeup" = "mac app".
|
| 111 |
+
- Never edit `node_modules` (global/Homebrew/npm/git installs too). Updates overwrite. Skill notes go in `tools.md` or `AGENTS.md`.
|
| 112 |
+
- Signal: "update fly" => `fly ssh console -a flawd-bot -C "bash -lc 'cd /data/clawd/moltbot && git pull --rebase origin main'"` then `fly machines restart e825232f34d058 -a flawd-bot`.
|
| 113 |
+
- When working on a GitHub Issue or PR, print the full URL at the end of the task.
|
| 114 |
+
- When answering questions, respond with high-confidence answers only: verify in code; do not guess.
|
| 115 |
+
- Never update the Carbon dependency.
|
| 116 |
+
- Any dependency with `pnpm.patchedDependencies` must use an exact version (no `^`/`~`).
|
| 117 |
+
- Patching dependencies (pnpm patches, overrides, or vendored changes) requires explicit approval; do not do this by default.
|
| 118 |
+
- CLI progress: use `src/cli/progress.ts` (`osc-progress` + `@clack/prompts` spinner); don’t hand-roll spinners/bars.
|
| 119 |
+
- Status output: keep tables + ANSI-safe wrapping (`src/terminal/table.ts`); `status --all` = read-only/pasteable, `status --deep` = probes.
|
| 120 |
+
- Gateway currently runs only as the menubar app; there is no separate LaunchAgent/helper label installed. Restart via the Moltbot Mac app or `scripts/restart-mac.sh`; to verify/kill use `launchctl print gui/$UID | grep moltbot` rather than assuming a fixed label. **When debugging on macOS, start/stop the gateway via the app, not ad-hoc tmux sessions; kill any temporary tunnels before handoff.**
|
| 121 |
+
- macOS logs: use `./scripts/clawlog.sh` to query unified logs for the Moltbot subsystem; it supports follow/tail/category filters and expects passwordless sudo for `/usr/bin/log`.
|
| 122 |
+
- If shared guardrails are available locally, review them; otherwise follow this repo's guidance.
|
| 123 |
+
- SwiftUI state management (iOS/macOS): prefer the `Observation` framework (`@Observable`, `@Bindable`) over `ObservableObject`/`@StateObject`; don’t introduce new `ObservableObject` unless required for compatibility, and migrate existing usages when touching related code.
|
| 124 |
+
- Connection providers: when adding a new connection, update every UI surface and docs (macOS app, web UI, mobile if applicable, onboarding/overview docs) and add matching status + configuration forms so provider lists and settings stay in sync.
|
| 125 |
+
- Version locations: `package.json` (CLI), `apps/android/app/build.gradle.kts` (versionName/versionCode), `apps/ios/Sources/Info.plist` + `apps/ios/Tests/Info.plist` (CFBundleShortVersionString/CFBundleVersion), `apps/macos/Sources/Moltbot/Resources/Info.plist` (CFBundleShortVersionString/CFBundleVersion), `docs/install/updating.md` (pinned npm version), `docs/platforms/mac/release.md` (APP_VERSION/APP_BUILD examples), Peekaboo Xcode projects/Info.plists (MARKETING_VERSION/CURRENT_PROJECT_VERSION).
|
| 126 |
+
- **Restart apps:** “restart iOS/Android apps” means rebuild (recompile/install) and relaunch, not just kill/launch.
|
| 127 |
+
- **Device checks:** before testing, verify connected real devices (iOS/Android) before reaching for simulators/emulators.
|
| 128 |
+
- iOS Team ID lookup: `security find-identity -p codesigning -v` → use Apple Development (…) TEAMID. Fallback: `defaults read com.apple.dt.Xcode IDEProvisioningTeamIdentifiers`.
|
| 129 |
+
- A2UI bundle hash: `src/canvas-host/a2ui/.bundle.hash` is auto-generated; ignore unexpected changes, and only regenerate via `pnpm canvas:a2ui:bundle` (or `scripts/bundle-a2ui.sh`) when needed. Commit the hash as a separate commit.
|
| 130 |
+
- Release signing/notary keys are managed outside the repo; follow internal release docs.
|
| 131 |
+
- Notary auth env vars (`APP_STORE_CONNECT_ISSUER_ID`, `APP_STORE_CONNECT_KEY_ID`, `APP_STORE_CONNECT_API_KEY_P8`) are expected in your environment (per internal release docs).
|
| 132 |
+
- **Multi-agent safety:** do **not** create/apply/drop `git stash` entries unless explicitly requested (this includes `git pull --rebase --autostash`). Assume other agents may be working; keep unrelated WIP untouched and avoid cross-cutting state changes.
|
| 133 |
+
- **Multi-agent safety:** when the user says "push", you may `git pull --rebase` to integrate latest changes (never discard other agents' work). When the user says "commit", scope to your changes only. When the user says "commit all", commit everything in grouped chunks.
|
| 134 |
+
- **Multi-agent safety:** do **not** create/remove/modify `git worktree` checkouts (or edit `.worktrees/*`) unless explicitly requested.
|
| 135 |
+
- **Multi-agent safety:** do **not** switch branches / check out a different branch unless explicitly requested.
|
| 136 |
+
- **Multi-agent safety:** running multiple agents is OK as long as each agent has its own session.
|
| 137 |
+
- **Multi-agent safety:** when you see unrecognized files, keep going; focus on your changes and commit only those.
|
| 138 |
+
- Lint/format churn:
|
| 139 |
+
- If staged+unstaged diffs are formatting-only, auto-resolve without asking.
|
| 140 |
+
- If commit/push already requested, auto-stage and include formatting-only follow-ups in the same commit (or a tiny follow-up commit if needed), no extra confirmation.
|
| 141 |
+
- Only ask when changes are semantic (logic/data/behavior).
|
| 142 |
+
- Lobster seam: use the shared CLI palette in `src/terminal/palette.ts` (no hardcoded colors); apply palette to onboarding/config prompts and other TTY UI output as needed.
|
| 143 |
+
- **Multi-agent safety:** focus reports on your edits; avoid guard-rail disclaimers unless truly blocked; when multiple agents touch the same file, continue if safe; end with a brief “other files present” note only if relevant.
|
| 144 |
+
- Bug investigations: read source code of relevant npm dependencies and all related local code before concluding; aim for high-confidence root cause.
|
| 145 |
+
- Code style: add brief comments for tricky logic; keep files under ~500 LOC when feasible (split/refactor as needed).
|
| 146 |
+
- Tool schema guardrails (google-antigravity): avoid `Type.Union` in tool input schemas; no `anyOf`/`oneOf`/`allOf`. Use `stringEnum`/`optionalStringEnum` (Type.Unsafe enum) for string lists, and `Type.Optional(...)` instead of `... | null`. Keep top-level tool schema as `type: "object"` with `properties`.
|
| 147 |
+
- Tool schema guardrails: avoid raw `format` property names in tool schemas; some validators treat `format` as a reserved keyword and reject the schema.
|
| 148 |
+
- When asked to open a “session” file, open the Pi session logs under `~/.clawdbot/agents/<agentId>/sessions/*.jsonl` (use the `agent=<id>` value in the Runtime line of the system prompt; newest unless a specific ID is given), not the default `sessions.json`. If logs are needed from another machine, SSH via Tailscale and read the same path there.
|
| 149 |
+
- Do not rebuild the macOS app over SSH; rebuilds must be run directly on the Mac.
|
| 150 |
+
- Never send streaming/partial replies to external messaging surfaces (WhatsApp, Telegram); only final replies should be delivered there. Streaming/tool events may still go to internal UIs/control channel.
|
| 151 |
+
- Voice wake forwarding tips:
|
| 152 |
+
- Command template should stay `moltbot-mac agent --message "${text}" --thinking low`; `VoiceWakeForwarder` already shell-escapes `${text}`. Don’t add extra quotes.
|
| 153 |
+
- launchd PATH is minimal; ensure the app’s launch agent PATH includes standard system paths plus your pnpm bin (typically `$HOME/Library/pnpm`) so `pnpm`/`moltbot` binaries resolve when invoked via `moltbot-mac`.
|
| 154 |
+
- For manual `moltbot message send` messages that include `!`, use the heredoc pattern noted below to avoid the Bash tool’s escaping.
|
| 155 |
+
- Release guardrails: do not change version numbers without operator’s explicit consent; always ask permission before running any npm publish/release step.
|
| 156 |
+
|
| 157 |
+
## NPM + 1Password (publish/verify)
|
| 158 |
+
- Use the 1password skill; all `op` commands must run inside a fresh tmux session.
|
| 159 |
+
- Sign in: `eval "$(op signin --account my.1password.com)"` (app unlocked + integration on).
|
| 160 |
+
- OTP: `op read 'op://Private/Npmjs/one-time password?attribute=otp'`.
|
| 161 |
+
- Publish: `npm publish --access public --otp="<otp>"` (run from the package dir).
|
| 162 |
+
- Verify without local npmrc side effects: `npm view <pkg> version --userconfig "$(mktemp)"`.
|
| 163 |
+
- Kill the tmux session after publish.
|
CHANGELOG.md
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
CLAUDE.md
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
AGENTS.md
|
CONTRIBUTING.md
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Contributing to Moltbot
|
| 2 |
+
|
| 3 |
+
Welcome to the lobster tank! 🦞
|
| 4 |
+
|
| 5 |
+
## Quick Links
|
| 6 |
+
- **GitHub:** https://github.com/moltbot/moltbot
|
| 7 |
+
- **Discord:** https://discord.gg/qkhbAGHRBT
|
| 8 |
+
- **X/Twitter:** [@steipete](https://x.com/steipete) / [@moltbot](https://x.com/moltbot)
|
| 9 |
+
|
| 10 |
+
## Maintainers
|
| 11 |
+
|
| 12 |
+
- **Peter Steinberger** - Benevolent Dictator
|
| 13 |
+
- GitHub: [@steipete](https://github.com/steipete) · X: [@steipete](https://x.com/steipete)
|
| 14 |
+
|
| 15 |
+
- **Shadow** - Discord + Slack subsystem
|
| 16 |
+
- GitHub: [@thewilloftheshadow](https://github.com/thewilloftheshadow) · X: [@4shad0wed](https://x.com/4shad0wed)
|
| 17 |
+
|
| 18 |
+
- **Jos** - Telegram, API, Nix mode
|
| 19 |
+
- GitHub: [@joshp123](https://github.com/joshp123) · X: [@jjpcodes](https://x.com/jjpcodes)
|
| 20 |
+
|
| 21 |
+
## How to Contribute
|
| 22 |
+
1. **Bugs & small fixes** → Open a PR!
|
| 23 |
+
2. **New features / architecture** → Start a [GitHub Discussion](https://github.com/moltbot/moltbot/discussions) or ask in Discord first
|
| 24 |
+
3. **Questions** → Discord #setup-help
|
| 25 |
+
|
| 26 |
+
## Before You PR
|
| 27 |
+
- Test locally with your Moltbot instance
|
| 28 |
+
- Run linter: `npm run lint`
|
| 29 |
+
- Keep PRs focused (one thing per PR)
|
| 30 |
+
- Describe what & why
|
| 31 |
+
|
| 32 |
+
## AI/Vibe-Coded PRs Welcome! 🤖
|
| 33 |
+
|
| 34 |
+
Built with Codex, Claude, or other AI tools? **Awesome - just mark it!**
|
| 35 |
+
|
| 36 |
+
Please include in your PR:
|
| 37 |
+
- [ ] Mark as AI-assisted in the PR title or description
|
| 38 |
+
- [ ] Note the degree of testing (untested / lightly tested / fully tested)
|
| 39 |
+
- [ ] Include prompts or session logs if possible (super helpful!)
|
| 40 |
+
- [ ] Confirm you understand what the code does
|
| 41 |
+
|
| 42 |
+
AI PRs are first-class citizens here. We just want transparency so reviewers know what to look for.
|
| 43 |
+
|
| 44 |
+
## Current Focus & Roadmap 🗺
|
| 45 |
+
|
| 46 |
+
We are currently prioritizing:
|
| 47 |
+
- **Stability**: Fixing edge cases in channel connections (WhatsApp/Telegram).
|
| 48 |
+
- **UX**: Improving the onboarding wizard and error messages.
|
| 49 |
+
- **Skills**: Expanding the library of bundled skills and improving the Skill Creation developer experience.
|
| 50 |
+
- **Performance**: Optimizing token usage and compaction logic.
|
| 51 |
+
|
| 52 |
+
Check the [GitHub Issues](https://github.com/moltbot/moltbot/issues) for "good first issue" labels!
|
Dockerfile
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
FROM node:22-bookworm
|
| 2 |
+
|
| 3 |
+
# Install Bun (required for build scripts)
|
| 4 |
+
RUN curl -fsSL https://bun.sh/install | bash
|
| 5 |
+
ENV PATH="/root/.bun/bin:${PATH}"
|
| 6 |
+
|
| 7 |
+
RUN corepack enable
|
| 8 |
+
|
| 9 |
+
WORKDIR /app
|
| 10 |
+
|
| 11 |
+
ARG CLAWDBOT_DOCKER_APT_PACKAGES=""
|
| 12 |
+
RUN if [ -n "$CLAWDBOT_DOCKER_APT_PACKAGES" ]; then \
|
| 13 |
+
apt-get update && \
|
| 14 |
+
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends $CLAWDBOT_DOCKER_APT_PACKAGES && \
|
| 15 |
+
apt-get clean && \
|
| 16 |
+
rm -rf /var/lib/apt/lists/* /var/cache/apt/archives/*; \
|
| 17 |
+
fi
|
| 18 |
+
|
| 19 |
+
COPY package.json pnpm-lock.yaml pnpm-workspace.yaml .npmrc ./
|
| 20 |
+
COPY ui/package.json ./ui/package.json
|
| 21 |
+
COPY patches ./patches
|
| 22 |
+
COPY scripts ./scripts
|
| 23 |
+
|
| 24 |
+
RUN pnpm install --frozen-lockfile
|
| 25 |
+
|
| 26 |
+
COPY . .
|
| 27 |
+
RUN pnpm build
|
| 28 |
+
# Force pnpm for UI build (Bun may fail on ARM/Synology architectures)
|
| 29 |
+
ENV CLAWDBOT_PREFER_PNPM=1
|
| 30 |
+
RUN pnpm ui:install
|
| 31 |
+
RUN pnpm ui:build
|
| 32 |
+
|
| 33 |
+
ENV NODE_ENV=production
|
| 34 |
+
|
| 35 |
+
# Security hardening: Run as non-root user
|
| 36 |
+
# The node:22-bookworm image includes a 'node' user (uid 1000)
|
| 37 |
+
# This reduces the attack surface by preventing container escape via root privileges
|
| 38 |
+
USER node
|
| 39 |
+
|
| 40 |
+
CMD ["node", "dist/index.js"]
|
Dockerfile.sandbox
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
FROM debian:bookworm-slim
|
| 2 |
+
|
| 3 |
+
ENV DEBIAN_FRONTEND=noninteractive
|
| 4 |
+
|
| 5 |
+
RUN apt-get update \
|
| 6 |
+
&& apt-get install -y --no-install-recommends \
|
| 7 |
+
bash \
|
| 8 |
+
ca-certificates \
|
| 9 |
+
curl \
|
| 10 |
+
git \
|
| 11 |
+
jq \
|
| 12 |
+
python3 \
|
| 13 |
+
ripgrep \
|
| 14 |
+
&& rm -rf /var/lib/apt/lists/*
|
| 15 |
+
|
| 16 |
+
CMD ["sleep", "infinity"]
|
Dockerfile.sandbox-browser
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
FROM debian:bookworm-slim
|
| 2 |
+
|
| 3 |
+
ENV DEBIAN_FRONTEND=noninteractive
|
| 4 |
+
|
| 5 |
+
RUN apt-get update \
|
| 6 |
+
&& apt-get install -y --no-install-recommends \
|
| 7 |
+
bash \
|
| 8 |
+
ca-certificates \
|
| 9 |
+
chromium \
|
| 10 |
+
curl \
|
| 11 |
+
fonts-liberation \
|
| 12 |
+
fonts-noto-color-emoji \
|
| 13 |
+
git \
|
| 14 |
+
jq \
|
| 15 |
+
novnc \
|
| 16 |
+
python3 \
|
| 17 |
+
socat \
|
| 18 |
+
websockify \
|
| 19 |
+
x11vnc \
|
| 20 |
+
xvfb \
|
| 21 |
+
&& rm -rf /var/lib/apt/lists/*
|
| 22 |
+
|
| 23 |
+
COPY scripts/sandbox-browser-entrypoint.sh /usr/local/bin/moltbot-sandbox-browser
|
| 24 |
+
RUN chmod +x /usr/local/bin/moltbot-sandbox-browser
|
| 25 |
+
|
| 26 |
+
EXPOSE 9222 5900 6080
|
| 27 |
+
|
| 28 |
+
CMD ["moltbot-sandbox-browser"]
|
LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
MIT License
|
| 2 |
+
|
| 3 |
+
Copyright (c) 2025 Peter Steinberger
|
| 4 |
+
|
| 5 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
| 6 |
+
of this software and associated documentation files (the "Software"), to deal
|
| 7 |
+
in the Software without restriction, including without limitation the rights
|
| 8 |
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
| 9 |
+
copies of the Software, and to permit persons to whom the Software is
|
| 10 |
+
furnished to do so, subject to the following conditions:
|
| 11 |
+
|
| 12 |
+
The above copyright notice and this permission notice shall be included in all
|
| 13 |
+
copies or substantial portions of the Software.
|
| 14 |
+
|
| 15 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
| 16 |
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
| 17 |
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
| 18 |
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
| 19 |
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
| 20 |
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
| 21 |
+
SOFTWARE.
|
README-header.png
ADDED
|
Git LFS Details
|
README.md
CHANGED
|
@@ -1,12 +1,512 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# 🦞 Clawdbot — Personal AI Assistant
|
| 2 |
+
|
| 3 |
+
<p align="center">
|
| 4 |
+
<img src="https://raw.githubusercontent.com/clawdbot/clawdbot/main/docs/whatsapp-clawd.jpg" alt="Clawdbot" width="400">
|
| 5 |
+
</p>
|
| 6 |
+
|
| 7 |
+
<p align="center">
|
| 8 |
+
<strong>EXFOLIATE! EXFOLIATE!</strong>
|
| 9 |
+
</p>
|
| 10 |
+
|
| 11 |
+
<p align="center">
|
| 12 |
+
<a href="https://github.com/clawdbot/clawdbot/actions/workflows/ci.yml?branch=main"><img src="https://img.shields.io/github/actions/workflow/status/clawdbot/clawdbot/ci.yml?branch=main&style=for-the-badge" alt="CI status"></a>
|
| 13 |
+
<a href="https://github.com/clawdbot/clawdbot/releases"><img src="https://img.shields.io/github/v/release/clawdbot/clawdbot?include_prereleases&style=for-the-badge" alt="GitHub release"></a>
|
| 14 |
+
<a href="https://deepwiki.com/clawdbot/clawdbot"><img src="https://img.shields.io/badge/DeepWiki-clawdbot-111111?style=for-the-badge" alt="DeepWiki"></a>
|
| 15 |
+
<a href="https://discord.gg/clawd"><img src="https://img.shields.io/discord/1456350064065904867?label=Discord&logo=discord&logoColor=white&color=5865F2&style=for-the-badge" alt="Discord"></a>
|
| 16 |
+
<a href="LICENSE"><img src="https://img.shields.io/badge/License-MIT-blue.svg?style=for-the-badge" alt="MIT License"></a>
|
| 17 |
+
</p>
|
| 18 |
+
|
| 19 |
+
**Clawdbot** is a *personal AI assistant* you run on your own devices.
|
| 20 |
+
It answers you on the channels you already use (WhatsApp, Telegram, Slack, Discord, Google Chat, Signal, iMessage, Microsoft Teams, WebChat), plus extension channels like BlueBubbles, Matrix, Zalo, and Zalo Personal. It can speak and listen on macOS/iOS/Android, and can render a live Canvas you control. The Gateway is just the control plane — the product is the assistant.
|
| 21 |
+
|
| 22 |
+
If you want a personal, single-user assistant that feels local, fast, and always-on, this is it.
|
| 23 |
+
|
| 24 |
+
[Website](https://molt.bot) · [Docs](https://docs.molt.bot) · [Getting Started](https://docs.molt.bot/start/getting-started) · [Updating](https://docs.molt.bot/install/updating) · [Showcase](https://docs.molt.bot/start/showcase) · [FAQ](https://docs.molt.bot/start/faq) · [Wizard](https://docs.molt.bot/start/wizard) · [Nix](https://github.com/clawdbot/nix-clawdbot) · [Docker](https://docs.molt.bot/install/docker) · [Discord](https://discord.gg/clawd)
|
| 25 |
+
|
| 26 |
+
Preferred setup: run the onboarding wizard (`clawdbot onboard`). It walks through gateway, workspace, channels, and skills. The CLI wizard is the recommended path and works on **macOS, Linux, and Windows (via WSL2; strongly recommended)**.
|
| 27 |
+
Works with npm, pnpm, or bun.
|
| 28 |
+
New install? Start here: [Getting started](https://docs.molt.bot/start/getting-started)
|
| 29 |
+
|
| 30 |
+
**Subscriptions (OAuth):**
|
| 31 |
+
- **[Anthropic](https://www.anthropic.com/)** (Claude Pro/Max)
|
| 32 |
+
- **[OpenAI](https://openai.com/)** (ChatGPT/Codex)
|
| 33 |
+
|
| 34 |
+
Model note: while any model is supported, I strongly recommend **Anthropic Pro/Max (100/200) + Opus 4.5** for long‑context strength and better prompt‑injection resistance. See [Onboarding](https://docs.molt.bot/start/onboarding).
|
| 35 |
+
|
| 36 |
+
## Models (selection + auth)
|
| 37 |
+
|
| 38 |
+
- Models config + CLI: [Models](https://docs.molt.bot/concepts/models)
|
| 39 |
+
- Auth profile rotation (OAuth vs API keys) + fallbacks: [Model failover](https://docs.molt.bot/concepts/model-failover)
|
| 40 |
+
|
| 41 |
+
## Install (recommended)
|
| 42 |
+
|
| 43 |
+
Runtime: **Node ≥22**.
|
| 44 |
+
|
| 45 |
+
```bash
|
| 46 |
+
npm install -g moltbot@latest
|
| 47 |
+
# or: pnpm add -g moltbot@latest
|
| 48 |
+
|
| 49 |
+
moltbot onboard --install-daemon
|
| 50 |
+
```
|
| 51 |
+
|
| 52 |
+
The wizard installs the Gateway daemon (launchd/systemd user service) so it stays running.
|
| 53 |
+
Legacy note: `clawdbot` remains available as a compatibility shim.
|
| 54 |
+
|
| 55 |
+
## Quick start (TL;DR)
|
| 56 |
+
|
| 57 |
+
Runtime: **Node ≥22**.
|
| 58 |
+
|
| 59 |
+
Full beginner guide (auth, pairing, channels): [Getting started](https://docs.molt.bot/start/getting-started)
|
| 60 |
+
|
| 61 |
+
```bash
|
| 62 |
+
moltbot onboard --install-daemon
|
| 63 |
+
|
| 64 |
+
moltbot gateway --port 18789 --verbose
|
| 65 |
+
|
| 66 |
+
# Send a message
|
| 67 |
+
moltbot message send --to +1234567890 --message "Hello from Moltbot"
|
| 68 |
+
|
| 69 |
+
# Talk to the assistant (optionally deliver back to any connected channel: WhatsApp/Telegram/Slack/Discord/Google Chat/Signal/iMessage/BlueBubbles/Microsoft Teams/Matrix/Zalo/Zalo Personal/WebChat)
|
| 70 |
+
moltbot agent --message "Ship checklist" --thinking high
|
| 71 |
+
```
|
| 72 |
+
|
| 73 |
+
Upgrading? [Updating guide](https://docs.molt.bot/install/updating) (and run `moltbot doctor`).
|
| 74 |
+
|
| 75 |
+
## Development channels
|
| 76 |
+
|
| 77 |
+
- **stable**: tagged releases (`vYYYY.M.D` or `vYYYY.M.D-<patch>`), npm dist-tag `latest`.
|
| 78 |
+
- **beta**: prerelease tags (`vYYYY.M.D-beta.N`), npm dist-tag `beta` (macOS app may be missing).
|
| 79 |
+
- **dev**: moving head of `main`, npm dist-tag `dev` (when published).
|
| 80 |
+
|
| 81 |
+
Switch channels (git + npm): `clawdbot update --channel stable|beta|dev`.
|
| 82 |
+
Details: [Development channels](https://docs.molt.bot/install/development-channels).
|
| 83 |
+
|
| 84 |
+
## From source (development)
|
| 85 |
+
|
| 86 |
+
Prefer `pnpm` for builds from source. Bun is optional for running TypeScript directly.
|
| 87 |
+
|
| 88 |
+
```bash
|
| 89 |
+
git clone https://github.com/clawdbot/clawdbot.git
|
| 90 |
+
cd clawdbot
|
| 91 |
+
|
| 92 |
+
pnpm install
|
| 93 |
+
pnpm ui:build # auto-installs UI deps on first run
|
| 94 |
+
pnpm build
|
| 95 |
+
|
| 96 |
+
pnpm moltbot onboard --install-daemon
|
| 97 |
+
|
| 98 |
+
# Dev loop (auto-reload on TS changes)
|
| 99 |
+
pnpm gateway:watch
|
| 100 |
+
```
|
| 101 |
+
|
| 102 |
+
Note: `pnpm moltbot ...` runs TypeScript directly (via `tsx`). `pnpm build` produces `dist/` for running via Node / the packaged `moltbot` binary.
|
| 103 |
+
|
| 104 |
+
## Security defaults (DM access)
|
| 105 |
+
|
| 106 |
+
Clawdbot connects to real messaging surfaces. Treat inbound DMs as **untrusted input**.
|
| 107 |
+
|
| 108 |
+
Full security guide: [Security](https://docs.molt.bot/gateway/security)
|
| 109 |
+
|
| 110 |
+
Default behavior on Telegram/WhatsApp/Signal/iMessage/Microsoft Teams/Discord/Google Chat/Slack:
|
| 111 |
+
- **DM pairing** (`dmPolicy="pairing"` / `channels.discord.dm.policy="pairing"` / `channels.slack.dm.policy="pairing"`): unknown senders receive a short pairing code and the bot does not process their message.
|
| 112 |
+
- Approve with: `clawdbot pairing approve <channel> <code>` (then the sender is added to a local allowlist store).
|
| 113 |
+
- Public inbound DMs require an explicit opt-in: set `dmPolicy="open"` and include `"*"` in the channel allowlist (`allowFrom` / `channels.discord.dm.allowFrom` / `channels.slack.dm.allowFrom`).
|
| 114 |
+
|
| 115 |
+
Run `clawdbot doctor` to surface risky/misconfigured DM policies.
|
| 116 |
+
|
| 117 |
+
## Highlights
|
| 118 |
+
|
| 119 |
+
- **[Local-first Gateway](https://docs.molt.bot/gateway)** — single control plane for sessions, channels, tools, and events.
|
| 120 |
+
- **[Multi-channel inbox](https://docs.molt.bot/channels)** — WhatsApp, Telegram, Slack, Discord, Google Chat, Signal, iMessage, BlueBubbles, Microsoft Teams, Matrix, Zalo, Zalo Personal, WebChat, macOS, iOS/Android.
|
| 121 |
+
- **[Multi-agent routing](https://docs.molt.bot/gateway/configuration)** — route inbound channels/accounts/peers to isolated agents (workspaces + per-agent sessions).
|
| 122 |
+
- **[Voice Wake](https://docs.molt.bot/nodes/voicewake) + [Talk Mode](https://docs.molt.bot/nodes/talk)** — always-on speech for macOS/iOS/Android with ElevenLabs.
|
| 123 |
+
- **[Live Canvas](https://docs.molt.bot/platforms/mac/canvas)** — agent-driven visual workspace with [A2UI](https://docs.molt.bot/platforms/mac/canvas#canvas-a2ui).
|
| 124 |
+
- **[First-class tools](https://docs.molt.bot/tools)** — browser, canvas, nodes, cron, sessions, and Discord/Slack actions.
|
| 125 |
+
- **[Companion apps](https://docs.molt.bot/platforms/macos)** — macOS menu bar app + iOS/Android [nodes](https://docs.molt.bot/nodes).
|
| 126 |
+
- **[Onboarding](https://docs.molt.bot/start/wizard) + [skills](https://docs.molt.bot/tools/skills)** — wizard-driven setup with bundled/managed/workspace skills.
|
| 127 |
+
|
| 128 |
+
## Star History
|
| 129 |
+
|
| 130 |
+
[](https://www.star-history.com/#clawdbot/clawdbot&type=date&legend=top-left)
|
| 131 |
+
|
| 132 |
+
## Everything we built so far
|
| 133 |
+
|
| 134 |
+
### Core platform
|
| 135 |
+
- [Gateway WS control plane](https://docs.molt.bot/gateway) with sessions, presence, config, cron, webhooks, [Control UI](https://docs.molt.bot/web), and [Canvas host](https://docs.molt.bot/platforms/mac/canvas#canvas-a2ui).
|
| 136 |
+
- [CLI surface](https://docs.molt.bot/tools/agent-send): gateway, agent, send, [wizard](https://docs.molt.bot/start/wizard), and [doctor](https://docs.molt.bot/gateway/doctor).
|
| 137 |
+
- [Pi agent runtime](https://docs.molt.bot/concepts/agent) in RPC mode with tool streaming and block streaming.
|
| 138 |
+
- [Session model](https://docs.molt.bot/concepts/session): `main` for direct chats, group isolation, activation modes, queue modes, reply-back. Group rules: [Groups](https://docs.molt.bot/concepts/groups).
|
| 139 |
+
- [Media pipeline](https://docs.molt.bot/nodes/images): images/audio/video, transcription hooks, size caps, temp file lifecycle. Audio details: [Audio](https://docs.molt.bot/nodes/audio).
|
| 140 |
+
|
| 141 |
+
### Channels
|
| 142 |
+
- [Channels](https://docs.molt.bot/channels): [WhatsApp](https://docs.molt.bot/channels/whatsapp) (Baileys), [Telegram](https://docs.molt.bot/channels/telegram) (grammY), [Slack](https://docs.molt.bot/channels/slack) (Bolt), [Discord](https://docs.molt.bot/channels/discord) (discord.js), [Google Chat](https://docs.molt.bot/channels/googlechat) (Chat API), [Signal](https://docs.molt.bot/channels/signal) (signal-cli), [iMessage](https://docs.molt.bot/channels/imessage) (imsg), [BlueBubbles](https://docs.molt.bot/channels/bluebubbles) (extension), [Microsoft Teams](https://docs.molt.bot/channels/msteams) (extension), [Matrix](https://docs.molt.bot/channels/matrix) (extension), [Zalo](https://docs.molt.bot/channels/zalo) (extension), [Zalo Personal](https://docs.molt.bot/channels/zalouser) (extension), [WebChat](https://docs.molt.bot/web/webchat).
|
| 143 |
+
- [Group routing](https://docs.molt.bot/concepts/group-messages): mention gating, reply tags, per-channel chunking and routing. Channel rules: [Channels](https://docs.molt.bot/channels).
|
| 144 |
+
|
| 145 |
+
### Apps + nodes
|
| 146 |
+
- [macOS app](https://docs.molt.bot/platforms/macos): menu bar control plane, [Voice Wake](https://docs.molt.bot/nodes/voicewake)/PTT, [Talk Mode](https://docs.molt.bot/nodes/talk) overlay, [WebChat](https://docs.molt.bot/web/webchat), debug tools, [remote gateway](https://docs.molt.bot/gateway/remote) control.
|
| 147 |
+
- [iOS node](https://docs.molt.bot/platforms/ios): [Canvas](https://docs.molt.bot/platforms/mac/canvas), [Voice Wake](https://docs.molt.bot/nodes/voicewake), [Talk Mode](https://docs.molt.bot/nodes/talk), camera, screen recording, Bonjour pairing.
|
| 148 |
+
- [Android node](https://docs.molt.bot/platforms/android): [Canvas](https://docs.molt.bot/platforms/mac/canvas), [Talk Mode](https://docs.molt.bot/nodes/talk), camera, screen recording, optional SMS.
|
| 149 |
+
- [macOS node mode](https://docs.molt.bot/nodes): system.run/notify + canvas/camera exposure.
|
| 150 |
+
|
| 151 |
+
### Tools + automation
|
| 152 |
+
- [Browser control](https://docs.molt.bot/tools/browser): dedicated clawd Chrome/Chromium, snapshots, actions, uploads, profiles.
|
| 153 |
+
- [Canvas](https://docs.molt.bot/platforms/mac/canvas): [A2UI](https://docs.molt.bot/platforms/mac/canvas#canvas-a2ui) push/reset, eval, snapshot.
|
| 154 |
+
- [Nodes](https://docs.molt.bot/nodes): camera snap/clip, screen record, [location.get](https://docs.molt.bot/nodes/location-command), notifications.
|
| 155 |
+
- [Cron + wakeups](https://docs.molt.bot/automation/cron-jobs); [webhooks](https://docs.molt.bot/automation/webhook); [Gmail Pub/Sub](https://docs.molt.bot/automation/gmail-pubsub).
|
| 156 |
+
- [Skills platform](https://docs.molt.bot/tools/skills): bundled, managed, and workspace skills with install gating + UI.
|
| 157 |
+
|
| 158 |
+
### Runtime + safety
|
| 159 |
+
- [Channel routing](https://docs.molt.bot/concepts/channel-routing), [retry policy](https://docs.molt.bot/concepts/retry), and [streaming/chunking](https://docs.molt.bot/concepts/streaming).
|
| 160 |
+
- [Presence](https://docs.molt.bot/concepts/presence), [typing indicators](https://docs.molt.bot/concepts/typing-indicators), and [usage tracking](https://docs.molt.bot/concepts/usage-tracking).
|
| 161 |
+
- [Models](https://docs.molt.bot/concepts/models), [model failover](https://docs.molt.bot/concepts/model-failover), and [session pruning](https://docs.molt.bot/concepts/session-pruning).
|
| 162 |
+
- [Security](https://docs.molt.bot/gateway/security) and [troubleshooting](https://docs.molt.bot/channels/troubleshooting).
|
| 163 |
+
|
| 164 |
+
### Ops + packaging
|
| 165 |
+
- [Control UI](https://docs.molt.bot/web) + [WebChat](https://docs.molt.bot/web/webchat) served directly from the Gateway.
|
| 166 |
+
- [Tailscale Serve/Funnel](https://docs.molt.bot/gateway/tailscale) or [SSH tunnels](https://docs.molt.bot/gateway/remote) with token/password auth.
|
| 167 |
+
- [Nix mode](https://docs.molt.bot/install/nix) for declarative config; [Docker](https://docs.molt.bot/install/docker)-based installs.
|
| 168 |
+
- [Doctor](https://docs.molt.bot/gateway/doctor) migrations, [logging](https://docs.molt.bot/logging).
|
| 169 |
+
|
| 170 |
+
## How it works (short)
|
| 171 |
+
|
| 172 |
+
```
|
| 173 |
+
WhatsApp / Telegram / Slack / Discord / Google Chat / Signal / iMessage / BlueBubbles / Microsoft Teams / Matrix / Zalo / Zalo Personal / WebChat
|
| 174 |
+
│
|
| 175 |
+
▼
|
| 176 |
+
┌───────────────────────────────┐
|
| 177 |
+
│ Gateway │
|
| 178 |
+
│ (control plane) │
|
| 179 |
+
│ ws://127.0.0.1:18789 │
|
| 180 |
+
└──────────────┬────────────────┘
|
| 181 |
+
│
|
| 182 |
+
├─ Pi agent (RPC)
|
| 183 |
+
├─ CLI (clawdbot …)
|
| 184 |
+
├─ WebChat UI
|
| 185 |
+
├─ macOS app
|
| 186 |
+
└─ iOS / Android nodes
|
| 187 |
+
```
|
| 188 |
+
|
| 189 |
+
## Key subsystems
|
| 190 |
+
|
| 191 |
+
- **[Gateway WebSocket network](https://docs.molt.bot/concepts/architecture)** — single WS control plane for clients, tools, and events (plus ops: [Gateway runbook](https://docs.molt.bot/gateway)).
|
| 192 |
+
- **[Tailscale exposure](https://docs.molt.bot/gateway/tailscale)** — Serve/Funnel for the Gateway dashboard + WS (remote access: [Remote](https://docs.molt.bot/gateway/remote)).
|
| 193 |
+
- **[Browser control](https://docs.molt.bot/tools/browser)** — clawd‑managed Chrome/Chromium with CDP control.
|
| 194 |
+
- **[Canvas + A2UI](https://docs.molt.bot/platforms/mac/canvas)** — agent‑driven visual workspace (A2UI host: [Canvas/A2UI](https://docs.molt.bot/platforms/mac/canvas#canvas-a2ui)).
|
| 195 |
+
- **[Voice Wake](https://docs.molt.bot/nodes/voicewake) + [Talk Mode](https://docs.molt.bot/nodes/talk)** — always‑on speech and continuous conversation.
|
| 196 |
+
- **[Nodes](https://docs.molt.bot/nodes)** — Canvas, camera snap/clip, screen record, `location.get`, notifications, plus macOS‑only `system.run`/`system.notify`.
|
| 197 |
+
|
| 198 |
+
## Tailscale access (Gateway dashboard)
|
| 199 |
+
|
| 200 |
+
Clawdbot can auto-configure Tailscale **Serve** (tailnet-only) or **Funnel** (public) while the Gateway stays bound to loopback. Configure `gateway.tailscale.mode`:
|
| 201 |
+
|
| 202 |
+
- `off`: no Tailscale automation (default).
|
| 203 |
+
- `serve`: tailnet-only HTTPS via `tailscale serve` (uses Tailscale identity headers by default).
|
| 204 |
+
- `funnel`: public HTTPS via `tailscale funnel` (requires shared password auth).
|
| 205 |
+
|
| 206 |
+
Notes:
|
| 207 |
+
- `gateway.bind` must stay `loopback` when Serve/Funnel is enabled (Clawdbot enforces this).
|
| 208 |
+
- Serve can be forced to require a password by setting `gateway.auth.mode: "password"` or `gateway.auth.allowTailscale: false`.
|
| 209 |
+
- Funnel refuses to start unless `gateway.auth.mode: "password"` is set.
|
| 210 |
+
- Optional: `gateway.tailscale.resetOnExit` to undo Serve/Funnel on shutdown.
|
| 211 |
+
|
| 212 |
+
Details: [Tailscale guide](https://docs.molt.bot/gateway/tailscale) · [Web surfaces](https://docs.molt.bot/web)
|
| 213 |
+
|
| 214 |
+
## Remote Gateway (Linux is great)
|
| 215 |
+
|
| 216 |
+
It’s perfectly fine to run the Gateway on a small Linux instance. Clients (macOS app, CLI, WebChat) can connect over **Tailscale Serve/Funnel** or **SSH tunnels**, and you can still pair device nodes (macOS/iOS/Android) to execute device‑local actions when needed.
|
| 217 |
+
|
| 218 |
+
- **Gateway host** runs the exec tool and channel connections by default.
|
| 219 |
+
- **Device nodes** run device‑local actions (`system.run`, camera, screen recording, notifications) via `node.invoke`.
|
| 220 |
+
In short: exec runs where the Gateway lives; device actions run where the device lives.
|
| 221 |
+
|
| 222 |
+
Details: [Remote access](https://docs.molt.bot/gateway/remote) · [Nodes](https://docs.molt.bot/nodes) · [Security](https://docs.molt.bot/gateway/security)
|
| 223 |
+
|
| 224 |
+
## macOS permissions via the Gateway protocol
|
| 225 |
+
|
| 226 |
+
The macOS app can run in **node mode** and advertises its capabilities + permission map over the Gateway WebSocket (`node.list` / `node.describe`). Clients can then execute local actions via `node.invoke`:
|
| 227 |
+
|
| 228 |
+
- `system.run` runs a local command and returns stdout/stderr/exit code; set `needsScreenRecording: true` to require screen-recording permission (otherwise you’ll get `PERMISSION_MISSING`).
|
| 229 |
+
- `system.notify` posts a user notification and fails if notifications are denied.
|
| 230 |
+
- `canvas.*`, `camera.*`, `screen.record`, and `location.get` are also routed via `node.invoke` and follow TCC permission status.
|
| 231 |
+
|
| 232 |
+
Elevated bash (host permissions) is separate from macOS TCC:
|
| 233 |
+
|
| 234 |
+
- Use `/elevated on|off` to toggle per‑session elevated access when enabled + allowlisted.
|
| 235 |
+
- Gateway persists the per‑session toggle via `sessions.patch` (WS method) alongside `thinkingLevel`, `verboseLevel`, `model`, `sendPolicy`, and `groupActivation`.
|
| 236 |
+
|
| 237 |
+
Details: [Nodes](https://docs.molt.bot/nodes) · [macOS app](https://docs.molt.bot/platforms/macos) · [Gateway protocol](https://docs.molt.bot/concepts/architecture)
|
| 238 |
+
|
| 239 |
+
## Agent to Agent (sessions_* tools)
|
| 240 |
+
|
| 241 |
+
- Use these to coordinate work across sessions without jumping between chat surfaces.
|
| 242 |
+
- `sessions_list` — discover active sessions (agents) and their metadata.
|
| 243 |
+
- `sessions_history` — fetch transcript logs for a session.
|
| 244 |
+
- `sessions_send` — message another session; optional reply‑back ping‑pong + announce step (`REPLY_SKIP`, `ANNOUNCE_SKIP`).
|
| 245 |
+
|
| 246 |
+
Details: [Session tools](https://docs.molt.bot/concepts/session-tool)
|
| 247 |
+
|
| 248 |
+
## Skills registry (ClawdHub)
|
| 249 |
+
|
| 250 |
+
ClawdHub is a minimal skill registry. With ClawdHub enabled, the agent can search for skills automatically and pull in new ones as needed.
|
| 251 |
+
|
| 252 |
+
[ClawdHub](https://ClawdHub.com)
|
| 253 |
+
|
| 254 |
+
## Chat commands
|
| 255 |
+
|
| 256 |
+
Send these in WhatsApp/Telegram/Slack/Google Chat/Microsoft Teams/WebChat (group commands are owner-only):
|
| 257 |
+
|
| 258 |
+
- `/status` — compact session status (model + tokens, cost when available)
|
| 259 |
+
- `/new` or `/reset` — reset the session
|
| 260 |
+
- `/compact` — compact session context (summary)
|
| 261 |
+
- `/think <level>` — off|minimal|low|medium|high|xhigh (GPT-5.2 + Codex models only)
|
| 262 |
+
- `/verbose on|off`
|
| 263 |
+
- `/usage off|tokens|full` — per-response usage footer
|
| 264 |
+
- `/restart` — restart the gateway (owner-only in groups)
|
| 265 |
+
- `/activation mention|always` — group activation toggle (groups only)
|
| 266 |
+
|
| 267 |
+
## Apps (optional)
|
| 268 |
+
|
| 269 |
+
The Gateway alone delivers a great experience. All apps are optional and add extra features.
|
| 270 |
+
|
| 271 |
+
If you plan to build/run companion apps, follow the platform runbooks below.
|
| 272 |
+
|
| 273 |
+
### macOS (Clawdbot.app) (optional)
|
| 274 |
+
|
| 275 |
+
- Menu bar control for the Gateway and health.
|
| 276 |
+
- Voice Wake + push-to-talk overlay.
|
| 277 |
+
- WebChat + debug tools.
|
| 278 |
+
- Remote gateway control over SSH.
|
| 279 |
+
|
| 280 |
+
Note: signed builds required for macOS permissions to stick across rebuilds (see `docs/mac/permissions.md`).
|
| 281 |
+
|
| 282 |
+
### iOS node (optional)
|
| 283 |
+
|
| 284 |
+
- Pairs as a node via the Bridge.
|
| 285 |
+
- Voice trigger forwarding + Canvas surface.
|
| 286 |
+
- Controlled via `clawdbot nodes …`.
|
| 287 |
+
|
| 288 |
+
Runbook: [iOS connect](https://docs.molt.bot/platforms/ios).
|
| 289 |
+
|
| 290 |
+
### Android node (optional)
|
| 291 |
+
|
| 292 |
+
- Pairs via the same Bridge + pairing flow as iOS.
|
| 293 |
+
- Exposes Canvas, Camera, and Screen capture commands.
|
| 294 |
+
- Runbook: [Android connect](https://docs.molt.bot/platforms/android).
|
| 295 |
+
|
| 296 |
+
## Agent workspace + skills
|
| 297 |
+
|
| 298 |
+
- Workspace root: `~/clawd` (configurable via `agents.defaults.workspace`).
|
| 299 |
+
- Injected prompt files: `AGENTS.md`, `SOUL.md`, `TOOLS.md`.
|
| 300 |
+
- Skills: `~/clawd/skills/<skill>/SKILL.md`.
|
| 301 |
+
|
| 302 |
+
## Configuration
|
| 303 |
+
|
| 304 |
+
Minimal `~/.clawdbot/clawdbot.json` (model + defaults):
|
| 305 |
+
|
| 306 |
+
```json5
|
| 307 |
+
{
|
| 308 |
+
agent: {
|
| 309 |
+
model: "anthropic/claude-opus-4-5"
|
| 310 |
+
}
|
| 311 |
+
}
|
| 312 |
+
```
|
| 313 |
+
|
| 314 |
+
[Full configuration reference (all keys + examples).](https://docs.molt.bot/gateway/configuration)
|
| 315 |
+
|
| 316 |
+
## Security model (important)
|
| 317 |
+
|
| 318 |
+
- **Default:** tools run on the host for the **main** session, so the agent has full access when it’s just you.
|
| 319 |
+
- **Group/channel safety:** set `agents.defaults.sandbox.mode: "non-main"` to run **non‑main sessions** (groups/channels) inside per‑session Docker sandboxes; bash then runs in Docker for those sessions.
|
| 320 |
+
- **Sandbox defaults:** allowlist `bash`, `process`, `read`, `write`, `edit`, `sessions_list`, `sessions_history`, `sessions_send`, `sessions_spawn`; denylist `browser`, `canvas`, `nodes`, `cron`, `discord`, `gateway`.
|
| 321 |
+
|
| 322 |
+
Details: [Security guide](https://docs.molt.bot/gateway/security) · [Docker + sandboxing](https://docs.molt.bot/install/docker) · [Sandbox config](https://docs.molt.bot/gateway/configuration)
|
| 323 |
+
|
| 324 |
+
### [WhatsApp](https://docs.molt.bot/channels/whatsapp)
|
| 325 |
+
|
| 326 |
+
- Link the device: `pnpm clawdbot channels login` (stores creds in `~/.clawdbot/credentials`).
|
| 327 |
+
- Allowlist who can talk to the assistant via `channels.whatsapp.allowFrom`.
|
| 328 |
+
- If `channels.whatsapp.groups` is set, it becomes a group allowlist; include `"*"` to allow all.
|
| 329 |
+
|
| 330 |
+
### [Telegram](https://docs.molt.bot/channels/telegram)
|
| 331 |
+
|
| 332 |
+
- Set `TELEGRAM_BOT_TOKEN` or `channels.telegram.botToken` (env wins).
|
| 333 |
+
- Optional: set `channels.telegram.groups` (with `channels.telegram.groups."*".requireMention`); when set, it is a group allowlist (include `"*"` to allow all). Also `channels.telegram.allowFrom` or `channels.telegram.webhookUrl` as needed.
|
| 334 |
+
|
| 335 |
+
```json5
|
| 336 |
+
{
|
| 337 |
+
channels: {
|
| 338 |
+
telegram: {
|
| 339 |
+
botToken: "123456:ABCDEF"
|
| 340 |
+
}
|
| 341 |
+
}
|
| 342 |
+
}
|
| 343 |
+
```
|
| 344 |
+
|
| 345 |
+
### [Slack](https://docs.molt.bot/channels/slack)
|
| 346 |
+
|
| 347 |
+
- Set `SLACK_BOT_TOKEN` + `SLACK_APP_TOKEN` (or `channels.slack.botToken` + `channels.slack.appToken`).
|
| 348 |
+
|
| 349 |
+
### [Discord](https://docs.molt.bot/channels/discord)
|
| 350 |
+
|
| 351 |
+
- Set `DISCORD_BOT_TOKEN` or `channels.discord.token` (env wins).
|
| 352 |
+
- Optional: set `commands.native`, `commands.text`, or `commands.useAccessGroups`, plus `channels.discord.dm.allowFrom`, `channels.discord.guilds`, or `channels.discord.mediaMaxMb` as needed.
|
| 353 |
+
|
| 354 |
+
```json5
|
| 355 |
+
{
|
| 356 |
+
channels: {
|
| 357 |
+
discord: {
|
| 358 |
+
token: "1234abcd"
|
| 359 |
+
}
|
| 360 |
+
}
|
| 361 |
+
}
|
| 362 |
+
```
|
| 363 |
+
|
| 364 |
+
### [Signal](https://docs.molt.bot/channels/signal)
|
| 365 |
+
|
| 366 |
+
- Requires `signal-cli` and a `channels.signal` config section.
|
| 367 |
+
|
| 368 |
+
### [iMessage](https://docs.molt.bot/channels/imessage)
|
| 369 |
+
|
| 370 |
+
- macOS only; Messages must be signed in.
|
| 371 |
+
- If `channels.imessage.groups` is set, it becomes a group allowlist; include `"*"` to allow all.
|
| 372 |
+
|
| 373 |
+
### [Microsoft Teams](https://docs.molt.bot/channels/msteams)
|
| 374 |
+
|
| 375 |
+
- Configure a Teams app + Bot Framework, then add a `msteams` config section.
|
| 376 |
+
- Allowlist who can talk via `msteams.allowFrom`; group access via `msteams.groupAllowFrom` or `msteams.groupPolicy: "open"`.
|
| 377 |
+
|
| 378 |
+
### [WebChat](https://docs.molt.bot/web/webchat)
|
| 379 |
+
|
| 380 |
+
- Uses the Gateway WebSocket; no separate WebChat port/config.
|
| 381 |
+
|
| 382 |
+
Browser control (optional):
|
| 383 |
+
|
| 384 |
+
```json5
|
| 385 |
+
{
|
| 386 |
+
browser: {
|
| 387 |
+
enabled: true,
|
| 388 |
+
color: "#FF4500"
|
| 389 |
+
}
|
| 390 |
+
}
|
| 391 |
+
```
|
| 392 |
+
|
| 393 |
+
## Docs
|
| 394 |
+
|
| 395 |
+
Use these when you’re past the onboarding flow and want the deeper reference.
|
| 396 |
+
- [Start with the docs index for navigation and “what’s where.”](https://docs.molt.bot)
|
| 397 |
+
- [Read the architecture overview for the gateway + protocol model.](https://docs.molt.bot/concepts/architecture)
|
| 398 |
+
- [Use the full configuration reference when you need every key and example.](https://docs.molt.bot/gateway/configuration)
|
| 399 |
+
- [Run the Gateway by the book with the operational runbook.](https://docs.molt.bot/gateway)
|
| 400 |
+
- [Learn how the Control UI/Web surfaces work and how to expose them safely.](https://docs.molt.bot/web)
|
| 401 |
+
- [Understand remote access over SSH tunnels or tailnets.](https://docs.molt.bot/gateway/remote)
|
| 402 |
+
- [Follow the onboarding wizard flow for a guided setup.](https://docs.molt.bot/start/wizard)
|
| 403 |
+
- [Wire external triggers via the webhook surface.](https://docs.molt.bot/automation/webhook)
|
| 404 |
+
- [Set up Gmail Pub/Sub triggers.](https://docs.molt.bot/automation/gmail-pubsub)
|
| 405 |
+
- [Learn the macOS menu bar companion details.](https://docs.molt.bot/platforms/mac/menu-bar)
|
| 406 |
+
- [Platform guides: Windows (WSL2)](https://docs.molt.bot/platforms/windows), [Linux](https://docs.molt.bot/platforms/linux), [macOS](https://docs.molt.bot/platforms/macos), [iOS](https://docs.molt.bot/platforms/ios), [Android](https://docs.molt.bot/platforms/android)
|
| 407 |
+
- [Debug common failures with the troubleshooting guide.](https://docs.molt.bot/channels/troubleshooting)
|
| 408 |
+
- [Review security guidance before exposing anything.](https://docs.molt.bot/gateway/security)
|
| 409 |
+
|
| 410 |
+
## Advanced docs (discovery + control)
|
| 411 |
+
|
| 412 |
+
- [Discovery + transports](https://docs.molt.bot/gateway/discovery)
|
| 413 |
+
- [Bonjour/mDNS](https://docs.molt.bot/gateway/bonjour)
|
| 414 |
+
- [Gateway pairing](https://docs.molt.bot/gateway/pairing)
|
| 415 |
+
- [Remote gateway README](https://docs.molt.bot/gateway/remote-gateway-readme)
|
| 416 |
+
- [Control UI](https://docs.molt.bot/web/control-ui)
|
| 417 |
+
- [Dashboard](https://docs.molt.bot/web/dashboard)
|
| 418 |
+
|
| 419 |
+
## Operations & troubleshooting
|
| 420 |
+
|
| 421 |
+
- [Health checks](https://docs.molt.bot/gateway/health)
|
| 422 |
+
- [Gateway lock](https://docs.molt.bot/gateway/gateway-lock)
|
| 423 |
+
- [Background process](https://docs.molt.bot/gateway/background-process)
|
| 424 |
+
- [Browser troubleshooting (Linux)](https://docs.molt.bot/tools/browser-linux-troubleshooting)
|
| 425 |
+
- [Logging](https://docs.molt.bot/logging)
|
| 426 |
+
|
| 427 |
+
## Deep dives
|
| 428 |
+
|
| 429 |
+
- [Agent loop](https://docs.molt.bot/concepts/agent-loop)
|
| 430 |
+
- [Presence](https://docs.molt.bot/concepts/presence)
|
| 431 |
+
- [TypeBox schemas](https://docs.molt.bot/concepts/typebox)
|
| 432 |
+
- [RPC adapters](https://docs.molt.bot/reference/rpc)
|
| 433 |
+
- [Queue](https://docs.molt.bot/concepts/queue)
|
| 434 |
+
|
| 435 |
+
## Workspace & skills
|
| 436 |
+
|
| 437 |
+
- [Skills config](https://docs.molt.bot/tools/skills-config)
|
| 438 |
+
- [Default AGENTS](https://docs.molt.bot/reference/AGENTS.default)
|
| 439 |
+
- [Templates: AGENTS](https://docs.molt.bot/reference/templates/AGENTS)
|
| 440 |
+
- [Templates: BOOTSTRAP](https://docs.molt.bot/reference/templates/BOOTSTRAP)
|
| 441 |
+
- [Templates: IDENTITY](https://docs.molt.bot/reference/templates/IDENTITY)
|
| 442 |
+
- [Templates: SOUL](https://docs.molt.bot/reference/templates/SOUL)
|
| 443 |
+
- [Templates: TOOLS](https://docs.molt.bot/reference/templates/TOOLS)
|
| 444 |
+
- [Templates: USER](https://docs.molt.bot/reference/templates/USER)
|
| 445 |
+
|
| 446 |
+
## Platform internals
|
| 447 |
+
|
| 448 |
+
- [macOS dev setup](https://docs.molt.bot/platforms/mac/dev-setup)
|
| 449 |
+
- [macOS menu bar](https://docs.molt.bot/platforms/mac/menu-bar)
|
| 450 |
+
- [macOS voice wake](https://docs.molt.bot/platforms/mac/voicewake)
|
| 451 |
+
- [iOS node](https://docs.molt.bot/platforms/ios)
|
| 452 |
+
- [Android node](https://docs.molt.bot/platforms/android)
|
| 453 |
+
- [Windows (WSL2)](https://docs.molt.bot/platforms/windows)
|
| 454 |
+
- [Linux app](https://docs.molt.bot/platforms/linux)
|
| 455 |
+
|
| 456 |
+
## Email hooks (Gmail)
|
| 457 |
+
|
| 458 |
+
- [docs.molt.bot/gmail-pubsub](https://docs.molt.bot/automation/gmail-pubsub)
|
| 459 |
+
|
| 460 |
+
## Clawd
|
| 461 |
+
|
| 462 |
+
Clawdbot was built for **Clawd**, a space lobster AI assistant. 🦞
|
| 463 |
+
by Peter Steinberger and the community.
|
| 464 |
+
|
| 465 |
+
- [clawd.me](https://clawd.me)
|
| 466 |
+
- [soul.md](https://soul.md)
|
| 467 |
+
- [steipete.me](https://steipete.me)
|
| 468 |
+
|
| 469 |
+
## Community
|
| 470 |
+
|
| 471 |
+
See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines, maintainers, and how to submit PRs.
|
| 472 |
+
AI/vibe-coded PRs welcome! 🤖
|
| 473 |
+
|
| 474 |
+
Special thanks to [Mario Zechner](https://mariozechner.at/) for his support and for
|
| 475 |
+
[pi-mono](https://github.com/badlogic/pi-mono).
|
| 476 |
+
|
| 477 |
+
Thanks to all clawtributors:
|
| 478 |
+
|
| 479 |
+
<p align="left">
|
| 480 |
+
<a href="https://github.com/steipete"><img src="https://avatars.githubusercontent.com/u/58493?v=4&s=48" width="48" height="48" alt="steipete" title="steipete"/></a> <a href="https://github.com/plum-dawg"><img src="https://avatars.githubusercontent.com/u/5909950?v=4&s=48" width="48" height="48" alt="plum-dawg" title="plum-dawg"/></a> <a href="https://github.com/bohdanpodvirnyi"><img src="https://avatars.githubusercontent.com/u/31819391?v=4&s=48" width="48" height="48" alt="bohdanpodvirnyi" title="bohdanpodvirnyi"/></a> <a href="https://github.com/iHildy"><img src="https://avatars.githubusercontent.com/u/25069719?v=4&s=48" width="48" height="48" alt="iHildy" title="iHildy"/></a> <a href="https://github.com/jaydenfyi"><img src="https://avatars.githubusercontent.com/u/213395523?v=4&s=48" width="48" height="48" alt="jaydenfyi" title="jaydenfyi"/></a> <a href="https://github.com/joaohlisboa"><img src="https://avatars.githubusercontent.com/u/8200873?v=4&s=48" width="48" height="48" alt="joaohlisboa" title="joaohlisboa"/></a> <a href="https://github.com/mneves75"><img src="https://avatars.githubusercontent.com/u/2423436?v=4&s=48" width="48" height="48" alt="mneves75" title="mneves75"/></a> <a href="https://github.com/MatthieuBizien"><img src="https://avatars.githubusercontent.com/u/173090?v=4&s=48" width="48" height="48" alt="MatthieuBizien" title="MatthieuBizien"/></a> <a href="https://github.com/MaudeBot"><img src="https://avatars.githubusercontent.com/u/255777700?v=4&s=48" width="48" height="48" alt="MaudeBot" title="MaudeBot"/></a> <a href="https://github.com/Glucksberg"><img src="https://avatars.githubusercontent.com/u/80581902?v=4&s=48" width="48" height="48" alt="Glucksberg" title="Glucksberg"/></a>
|
| 481 |
+
<a href="https://github.com/rahthakor"><img src="https://avatars.githubusercontent.com/u/8470553?v=4&s=48" width="48" height="48" alt="rahthakor" title="rahthakor"/></a> <a href="https://github.com/vrknetha"><img src="https://avatars.githubusercontent.com/u/20596261?v=4&s=48" width="48" height="48" alt="vrknetha" title="vrknetha"/></a> <a href="https://github.com/radek-paclt"><img src="https://avatars.githubusercontent.com/u/50451445?v=4&s=48" width="48" height="48" alt="radek-paclt" title="radek-paclt"/></a> <a href="https://github.com/tobiasbischoff"><img src="https://avatars.githubusercontent.com/u/711564?v=4&s=48" width="48" height="48" alt="Tobias Bischoff" title="Tobias Bischoff"/></a> <a href="https://github.com/joshp123"><img src="https://avatars.githubusercontent.com/u/1497361?v=4&s=48" width="48" height="48" alt="joshp123" title="joshp123"/></a> <a href="https://github.com/czekaj"><img src="https://avatars.githubusercontent.com/u/1464539?v=4&s=48" width="48" height="48" alt="czekaj" title="czekaj"/></a> <a href="https://github.com/mukhtharcm"><img src="https://avatars.githubusercontent.com/u/56378562?v=4&s=48" width="48" height="48" alt="mukhtharcm" title="mukhtharcm"/></a> <a href="https://github.com/sebslight"><img src="https://avatars.githubusercontent.com/u/19554889?v=4&s=48" width="48" height="48" alt="sebslight" title="sebslight"/></a> <a href="https://github.com/maxsumrall"><img src="https://avatars.githubusercontent.com/u/628843?v=4&s=48" width="48" height="48" alt="maxsumrall" title="maxsumrall"/></a> <a href="https://github.com/xadenryan"><img src="https://avatars.githubusercontent.com/u/165437834?v=4&s=48" width="48" height="48" alt="xadenryan" title="xadenryan"/></a>
|
| 482 |
+
<a href="https://github.com/rodrigouroz"><img src="https://avatars.githubusercontent.com/u/384037?v=4&s=48" width="48" height="48" alt="rodrigouroz" title="rodrigouroz"/></a> <a href="https://github.com/juanpablodlc"><img src="https://avatars.githubusercontent.com/u/92012363?v=4&s=48" width="48" height="48" alt="juanpablodlc" title="juanpablodlc"/></a> <a href="https://github.com/hsrvc"><img src="https://avatars.githubusercontent.com/u/129702169?v=4&s=48" width="48" height="48" alt="hsrvc" title="hsrvc"/></a> <a href="https://github.com/magimetal"><img src="https://avatars.githubusercontent.com/u/36491250?v=4&s=48" width="48" height="48" alt="magimetal" title="magimetal"/></a> <a href="https://github.com/zerone0x"><img src="https://avatars.githubusercontent.com/u/39543393?v=4&s=48" width="48" height="48" alt="zerone0x" title="zerone0x"/></a> <a href="https://github.com/meaningfool"><img src="https://avatars.githubusercontent.com/u/2862331?v=4&s=48" width="48" height="48" alt="meaningfool" title="meaningfool"/></a> <a href="https://github.com/tyler6204"><img src="https://avatars.githubusercontent.com/u/64381258?v=4&s=48" width="48" height="48" alt="tyler6204" title="tyler6204"/></a> <a href="https://github.com/vignesh07"><img src="https://avatars.githubusercontent.com/u/1436853?v=4&s=48" width="48" height="48" alt="vignesh07" title="vignesh07"/></a> <a href="https://github.com/patelhiren"><img src="https://avatars.githubusercontent.com/u/172098?v=4&s=48" width="48" height="48" alt="patelhiren" title="patelhiren"/></a> <a href="https://github.com/NicholasSpisak"><img src="https://avatars.githubusercontent.com/u/129075147?v=4&s=48" width="48" height="48" alt="NicholasSpisak" title="NicholasSpisak"/></a>
|
| 483 |
+
<a href="https://github.com/jonisjongithub"><img src="https://avatars.githubusercontent.com/u/86072337?v=4&s=48" width="48" height="48" alt="jonisjongithub" title="jonisjongithub"/></a> <a href="https://github.com/AbhisekBasu1"><img src="https://avatars.githubusercontent.com/u/40645221?v=4&s=48" width="48" height="48" alt="abhisekbasu1" title="abhisekbasu1"/></a> <a href="https://github.com/jamesgroat"><img src="https://avatars.githubusercontent.com/u/2634024?v=4&s=48" width="48" height="48" alt="jamesgroat" title="jamesgroat"/></a> <a href="https://github.com/claude"><img src="https://avatars.githubusercontent.com/u/81847?v=4&s=48" width="48" height="48" alt="claude" title="claude"/></a> <a href="https://github.com/JustYannicc"><img src="https://avatars.githubusercontent.com/u/52761674?v=4&s=48" width="48" height="48" alt="JustYannicc" title="JustYannicc"/></a> <a href="https://github.com/Hyaxia"><img src="https://avatars.githubusercontent.com/u/36747317?v=4&s=48" width="48" height="48" alt="Hyaxia" title="Hyaxia"/></a> <a href="https://github.com/dantelex"><img src="https://avatars.githubusercontent.com/u/631543?v=4&s=48" width="48" height="48" alt="dantelex" title="dantelex"/></a> <a href="https://github.com/SocialNerd42069"><img src="https://avatars.githubusercontent.com/u/118244303?v=4&s=48" width="48" height="48" alt="SocialNerd42069" title="SocialNerd42069"/></a> <a href="https://github.com/daveonkels"><img src="https://avatars.githubusercontent.com/u/533642?v=4&s=48" width="48" height="48" alt="daveonkels" title="daveonkels"/></a> <a href="https://github.com/apps/google-labs-jules"><img src="https://avatars.githubusercontent.com/in/842251?v=4&s=48" width="48" height="48" alt="google-labs-jules[bot]" title="google-labs-jules[bot]"/></a>
|
| 484 |
+
<a href="https://github.com/lc0rp"><img src="https://avatars.githubusercontent.com/u/2609441?v=4&s=48" width="48" height="48" alt="lc0rp" title="lc0rp"/></a> <a href="https://github.com/mousberg"><img src="https://avatars.githubusercontent.com/u/57605064?v=4&s=48" width="48" height="48" alt="mousberg" title="mousberg"/></a> <a href="https://github.com/mteam88"><img src="https://avatars.githubusercontent.com/u/84196639?v=4&s=48" width="48" height="48" alt="mteam88" title="mteam88"/></a> <a href="https://github.com/hirefrank"><img src="https://avatars.githubusercontent.com/u/183158?v=4&s=48" width="48" height="48" alt="hirefrank" title="hirefrank"/></a> <a href="https://github.com/joeynyc"><img src="https://avatars.githubusercontent.com/u/17919866?v=4&s=48" width="48" height="48" alt="joeynyc" title="joeynyc"/></a> <a href="https://github.com/orlyjamie"><img src="https://avatars.githubusercontent.com/u/6668807?v=4&s=48" width="48" height="48" alt="orlyjamie" title="orlyjamie"/></a> <a href="https://github.com/dbhurley"><img src="https://avatars.githubusercontent.com/u/5251425?v=4&s=48" width="48" height="48" alt="dbhurley" title="dbhurley"/></a> <a href="https://github.com/mbelinky"><img src="https://avatars.githubusercontent.com/u/132747814?v=4&s=48" width="48" height="48" alt="Mariano Belinky" title="Mariano Belinky"/></a> <a href="https://github.com/omniwired"><img src="https://avatars.githubusercontent.com/u/322761?v=4&s=48" width="48" height="48" alt="Eng. Juan Combetto" title="Eng. Juan Combetto"/></a> <a href="https://github.com/TSavo"><img src="https://avatars.githubusercontent.com/u/877990?v=4&s=48" width="48" height="48" alt="TSavo" title="TSavo"/></a>
|
| 485 |
+
<a href="https://github.com/julianengel"><img src="https://avatars.githubusercontent.com/u/10634231?v=4&s=48" width="48" height="48" alt="julianengel" title="julianengel"/></a> <a href="https://github.com/bradleypriest"><img src="https://avatars.githubusercontent.com/u/167215?v=4&s=48" width="48" height="48" alt="bradleypriest" title="bradleypriest"/></a> <a href="https://github.com/benithors"><img src="https://avatars.githubusercontent.com/u/20652882?v=4&s=48" width="48" height="48" alt="benithors" title="benithors"/></a> <a href="https://github.com/rohannagpal"><img src="https://avatars.githubusercontent.com/u/4009239?v=4&s=48" width="48" height="48" alt="rohannagpal" title="rohannagpal"/></a> <a href="https://github.com/timolins"><img src="https://avatars.githubusercontent.com/u/1440854?v=4&s=48" width="48" height="48" alt="timolins" title="timolins"/></a> <a href="https://github.com/f-trycua"><img src="https://avatars.githubusercontent.com/u/195596869?v=4&s=48" width="48" height="48" alt="f-trycua" title="f-trycua"/></a> <a href="https://github.com/benostein"><img src="https://avatars.githubusercontent.com/u/31802821?v=4&s=48" width="48" height="48" alt="benostein" title="benostein"/></a> <a href="https://github.com/Nachx639"><img src="https://avatars.githubusercontent.com/u/71144023?v=4&s=48" width="48" height="48" alt="nachx639" title="nachx639"/></a> <a href="https://github.com/pvoo"><img src="https://avatars.githubusercontent.com/u/20116814?v=4&s=48" width="48" height="48" alt="pvoo" title="pvoo"/></a> <a href="https://github.com/sreekaransrinath"><img src="https://avatars.githubusercontent.com/u/50989977?v=4&s=48" width="48" height="48" alt="sreekaransrinath" title="sreekaransrinath"/></a>
|
| 486 |
+
<a href="https://github.com/gupsammy"><img src="https://avatars.githubusercontent.com/u/20296019?v=4&s=48" width="48" height="48" alt="gupsammy" title="gupsammy"/></a> <a href="https://github.com/cristip73"><img src="https://avatars.githubusercontent.com/u/24499421?v=4&s=48" width="48" height="48" alt="cristip73" title="cristip73"/></a> <a href="https://github.com/stefangalescu"><img src="https://avatars.githubusercontent.com/u/52995748?v=4&s=48" width="48" height="48" alt="stefangalescu" title="stefangalescu"/></a> <a href="https://github.com/nachoiacovino"><img src="https://avatars.githubusercontent.com/u/50103937?v=4&s=48" width="48" height="48" alt="nachoiacovino" title="nachoiacovino"/></a> <a href="https://github.com/vsabavat"><img src="https://avatars.githubusercontent.com/u/50385532?v=4&s=48" width="48" height="48" alt="Vasanth Rao Naik Sabavat" title="Vasanth Rao Naik Sabavat"/></a> <a href="https://github.com/petter-b"><img src="https://avatars.githubusercontent.com/u/62076402?v=4&s=48" width="48" height="48" alt="petter-b" title="petter-b"/></a> <a href="https://github.com/cpojer"><img src="https://avatars.githubusercontent.com/u/13352?v=4&s=48" width="48" height="48" alt="cpojer" title="cpojer"/></a> <a href="https://github.com/scald"><img src="https://avatars.githubusercontent.com/u/1215913?v=4&s=48" width="48" height="48" alt="scald" title="scald"/></a> <a href="https://github.com/gumadeiras"><img src="https://avatars.githubusercontent.com/u/5599352?v=4&s=48" width="48" height="48" alt="gumadeiras" title="gumadeiras"/></a> <a href="https://github.com/andranik-sahakyan"><img src="https://avatars.githubusercontent.com/u/8908029?v=4&s=48" width="48" height="48" alt="andranik-sahakyan" title="andranik-sahakyan"/></a>
|
| 487 |
+
<a href="https://github.com/davidguttman"><img src="https://avatars.githubusercontent.com/u/431696?v=4&s=48" width="48" height="48" alt="davidguttman" title="davidguttman"/></a> <a href="https://github.com/thewilloftheshadow"><img src="https://avatars.githubusercontent.com/u/35580099?v=4&s=48" width="48" height="48" alt="thewilloftheshadow" title="thewilloftheshadow"/></a> <a href="https://github.com/sleontenko"><img src="https://avatars.githubusercontent.com/u/7135949?v=4&s=48" width="48" height="48" alt="sleontenko" title="sleontenko"/></a> <a href="https://github.com/denysvitali"><img src="https://avatars.githubusercontent.com/u/4939519?v=4&s=48" width="48" height="48" alt="denysvitali" title="denysvitali"/></a> <a href="https://github.com/shakkernerd"><img src="https://avatars.githubusercontent.com/u/165377636?v=4&s=48" width="48" height="48" alt="shakkernerd" title="shakkernerd"/></a> <a href="https://github.com/sircrumpet"><img src="https://avatars.githubusercontent.com/u/4436535?v=4&s=48" width="48" height="48" alt="sircrumpet" title="sircrumpet"/></a> <a href="https://github.com/peschee"><img src="https://avatars.githubusercontent.com/u/63866?v=4&s=48" width="48" height="48" alt="peschee" title="peschee"/></a> <a href="https://github.com/rafaelreis-r"><img src="https://avatars.githubusercontent.com/u/57492577?v=4&s=48" width="48" height="48" alt="rafaelreis-r" title="rafaelreis-r"/></a> <a href="https://github.com/dominicnunez"><img src="https://avatars.githubusercontent.com/u/43616264?v=4&s=48" width="48" height="48" alt="dominicnunez" title="dominicnunez"/></a> <a href="https://github.com/ratulsarna"><img src="https://avatars.githubusercontent.com/u/105903728?v=4&s=48" width="48" height="48" alt="ratulsarna" title="ratulsarna"/></a>
|
| 488 |
+
<a href="https://github.com/lutr0"><img src="https://avatars.githubusercontent.com/u/76906369?v=4&s=48" width="48" height="48" alt="lutr0" title="lutr0"/></a> <a href="https://github.com/danielz1z"><img src="https://avatars.githubusercontent.com/u/235270390?v=4&s=48" width="48" height="48" alt="danielz1z" title="danielz1z"/></a> <a href="https://github.com/AdeboyeDN"><img src="https://avatars.githubusercontent.com/u/65312338?v=4&s=48" width="48" height="48" alt="AdeboyeDN" title="AdeboyeDN"/></a> <a href="https://github.com/Alg0rix"><img src="https://avatars.githubusercontent.com/u/53804949?v=4&s=48" width="48" height="48" alt="Alg0rix" title="Alg0rix"/></a> <a href="https://github.com/emanuelst"><img src="https://avatars.githubusercontent.com/u/9994339?v=4&s=48" width="48" height="48" alt="emanuelst" title="emanuelst"/></a> <a href="https://github.com/KristijanJovanovski"><img src="https://avatars.githubusercontent.com/u/8942284?v=4&s=48" width="48" height="48" alt="KristijanJovanovski" title="KristijanJovanovski"/></a> <a href="https://github.com/rdev"><img src="https://avatars.githubusercontent.com/u/8418866?v=4&s=48" width="48" height="48" alt="rdev" title="rdev"/></a> <a href="https://github.com/rhuanssauro"><img src="https://avatars.githubusercontent.com/u/164682191?v=4&s=48" width="48" height="48" alt="rhuanssauro" title="rhuanssauro"/></a> <a href="https://github.com/joshrad-dev"><img src="https://avatars.githubusercontent.com/u/62785552?v=4&s=48" width="48" height="48" alt="joshrad-dev" title="joshrad-dev"/></a> <a href="https://github.com/kiranjd"><img src="https://avatars.githubusercontent.com/u/25822851?v=4&s=48" width="48" height="48" alt="kiranjd" title="kiranjd"/></a>
|
| 489 |
+
<a href="https://github.com/osolmaz"><img src="https://avatars.githubusercontent.com/u/2453968?v=4&s=48" width="48" height="48" alt="osolmaz" title="osolmaz"/></a> <a href="https://github.com/adityashaw2"><img src="https://avatars.githubusercontent.com/u/41204444?v=4&s=48" width="48" height="48" alt="adityashaw2" title="adityashaw2"/></a> <a href="https://github.com/CashWilliams"><img src="https://avatars.githubusercontent.com/u/613573?v=4&s=48" width="48" height="48" alt="CashWilliams" title="CashWilliams"/></a> <a href="https://github.com/search?q=sheeek"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="sheeek" title="sheeek"/></a> <a href="https://github.com/artuskg"><img src="https://avatars.githubusercontent.com/u/11966157?v=4&s=48" width="48" height="48" alt="artuskg" title="artuskg"/></a> <a href="https://github.com/Takhoffman"><img src="https://avatars.githubusercontent.com/u/781889?v=4&s=48" width="48" height="48" alt="Takhoffman" title="Takhoffman"/></a> <a href="https://github.com/onutc"><img src="https://avatars.githubusercontent.com/u/152018508?v=4&s=48" width="48" height="48" alt="onutc" title="onutc"/></a> <a href="https://github.com/pauloportella"><img src="https://avatars.githubusercontent.com/u/22947229?v=4&s=48" width="48" height="48" alt="pauloportella" title="pauloportella"/></a> <a href="https://github.com/neooriginal"><img src="https://avatars.githubusercontent.com/u/54811660?v=4&s=48" width="48" height="48" alt="neooriginal" title="neooriginal"/></a> <a href="https://github.com/ManuelHettich"><img src="https://avatars.githubusercontent.com/u/17690367?v=4&s=48" width="48" height="48" alt="manuelhettich" title="manuelhettich"/></a>
|
| 490 |
+
<a href="https://github.com/minghinmatthewlam"><img src="https://avatars.githubusercontent.com/u/14224566?v=4&s=48" width="48" height="48" alt="minghinmatthewlam" title="minghinmatthewlam"/></a> <a href="https://github.com/myfunc"><img src="https://avatars.githubusercontent.com/u/19294627?v=4&s=48" width="48" height="48" alt="myfunc" title="myfunc"/></a> <a href="https://github.com/travisirby"><img src="https://avatars.githubusercontent.com/u/5958376?v=4&s=48" width="48" height="48" alt="travisirby" title="travisirby"/></a> <a href="https://github.com/buddyh"><img src="https://avatars.githubusercontent.com/u/31752869?v=4&s=48" width="48" height="48" alt="buddyh" title="buddyh"/></a> <a href="https://github.com/connorshea"><img src="https://avatars.githubusercontent.com/u/2977353?v=4&s=48" width="48" height="48" alt="connorshea" title="connorshea"/></a> <a href="https://github.com/kyleok"><img src="https://avatars.githubusercontent.com/u/58307870?v=4&s=48" width="48" height="48" alt="kyleok" title="kyleok"/></a> <a href="https://github.com/mcinteerj"><img src="https://avatars.githubusercontent.com/u/3613653?v=4&s=48" width="48" height="48" alt="mcinteerj" title="mcinteerj"/></a> <a href="https://github.com/apps/dependabot"><img src="https://avatars.githubusercontent.com/in/29110?v=4&s=48" width="48" height="48" alt="dependabot[bot]" title="dependabot[bot]"/></a> <a href="https://github.com/John-Rood"><img src="https://avatars.githubusercontent.com/u/62669593?v=4&s=48" width="48" height="48" alt="John-Rood" title="John-Rood"/></a> <a href="https://github.com/obviyus"><img src="https://avatars.githubusercontent.com/u/22031114?v=4&s=48" width="48" height="48" alt="obviyus" title="obviyus"/></a>
|
| 491 |
+
<a href="https://github.com/timkrase"><img src="https://avatars.githubusercontent.com/u/38947626?v=4&s=48" width="48" height="48" alt="timkrase" title="timkrase"/></a> <a href="https://github.com/uos-status"><img src="https://avatars.githubusercontent.com/u/255712580?v=4&s=48" width="48" height="48" alt="uos-status" title="uos-status"/></a> <a href="https://github.com/gerardward2007"><img src="https://avatars.githubusercontent.com/u/3002155?v=4&s=48" width="48" height="48" alt="gerardward2007" title="gerardward2007"/></a> <a href="https://github.com/roshanasingh4"><img src="https://avatars.githubusercontent.com/u/88576930?v=4&s=48" width="48" height="48" alt="roshanasingh4" title="roshanasingh4"/></a> <a href="https://github.com/tosh-hamburg"><img src="https://avatars.githubusercontent.com/u/58424326?v=4&s=48" width="48" height="48" alt="tosh-hamburg" title="tosh-hamburg"/></a> <a href="https://github.com/azade-c"><img src="https://avatars.githubusercontent.com/u/252790079?v=4&s=48" width="48" height="48" alt="azade-c" title="azade-c"/></a> <a href="https://github.com/JonUleis"><img src="https://avatars.githubusercontent.com/u/7644941?v=4&s=48" width="48" height="48" alt="JonUleis" title="JonUleis"/></a> <a href="https://github.com/bjesuiter"><img src="https://avatars.githubusercontent.com/u/2365676?v=4&s=48" width="48" height="48" alt="bjesuiter" title="bjesuiter"/></a> <a href="https://github.com/cheeeee"><img src="https://avatars.githubusercontent.com/u/21245729?v=4&s=48" width="48" height="48" alt="cheeeee" title="cheeeee"/></a> <a href="https://github.com/robbyczgw-cla"><img src="https://avatars.githubusercontent.com/u/239660374?v=4&s=48" width="48" height="48" alt="robbyczgw-cla" title="robbyczgw-cla"/></a>
|
| 492 |
+
<a href="https://github.com/dlauer"><img src="https://avatars.githubusercontent.com/u/757041?v=4&s=48" width="48" height="48" alt="dlauer" title="dlauer"/></a> <a href="https://github.com/j1philli"><img src="https://avatars.githubusercontent.com/u/3744255?v=4&s=48" width="48" height="48" alt="Josh Phillips" title="Josh Phillips"/></a> <a href="https://github.com/YuriNachos"><img src="https://avatars.githubusercontent.com/u/19365375?v=4&s=48" width="48" height="48" alt="YuriNachos" title="YuriNachos"/></a> <a href="https://github.com/pookNast"><img src="https://avatars.githubusercontent.com/u/14242552?v=4&s=48" width="48" height="48" alt="pookNast" title="pookNast"/></a> <a href="https://github.com/Whoaa512"><img src="https://avatars.githubusercontent.com/u/1581943?v=4&s=48" width="48" height="48" alt="Whoaa512" title="Whoaa512"/></a> <a href="https://github.com/chriseidhof"><img src="https://avatars.githubusercontent.com/u/5382?v=4&s=48" width="48" height="48" alt="chriseidhof" title="chriseidhof"/></a> <a href="https://github.com/ngutman"><img src="https://avatars.githubusercontent.com/u/1540134?v=4&s=48" width="48" height="48" alt="ngutman" title="ngutman"/></a> <a href="https://github.com/ysqander"><img src="https://avatars.githubusercontent.com/u/80843820?v=4&s=48" width="48" height="48" alt="ysqander" title="ysqander"/></a> <a href="https://github.com/aj47"><img src="https://avatars.githubusercontent.com/u/8023513?v=4&s=48" width="48" height="48" alt="aj47" title="aj47"/></a> <a href="https://github.com/superman32432432"><img src="https://avatars.githubusercontent.com/u/7228420?v=4&s=48" width="48" height="48" alt="superman32432432" title="superman32432432"/></a>
|
| 493 |
+
<a href="https://github.com/search?q=Yurii%20Chukhlib"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Yurii Chukhlib" title="Yurii Chukhlib"/></a> <a href="https://github.com/grp06"><img src="https://avatars.githubusercontent.com/u/1573959?v=4&s=48" width="48" height="48" alt="grp06" title="grp06"/></a> <a href="https://github.com/antons"><img src="https://avatars.githubusercontent.com/u/129705?v=4&s=48" width="48" height="48" alt="antons" title="antons"/></a> <a href="https://github.com/austinm911"><img src="https://avatars.githubusercontent.com/u/31991302?v=4&s=48" width="48" height="48" alt="austinm911" title="austinm911"/></a> <a href="https://github.com/apps/blacksmith-sh"><img src="https://avatars.githubusercontent.com/in/807020?v=4&s=48" width="48" height="48" alt="blacksmith-sh[bot]" title="blacksmith-sh[bot]"/></a> <a href="https://github.com/damoahdominic"><img src="https://avatars.githubusercontent.com/u/4623434?v=4&s=48" width="48" height="48" alt="damoahdominic" title="damoahdominic"/></a> <a href="https://github.com/dan-dr"><img src="https://avatars.githubusercontent.com/u/6669808?v=4&s=48" width="48" height="48" alt="dan-dr" title="dan-dr"/></a> <a href="https://github.com/HeimdallStrategy"><img src="https://avatars.githubusercontent.com/u/223014405?v=4&s=48" width="48" height="48" alt="HeimdallStrategy" title="HeimdallStrategy"/></a> <a href="https://github.com/imfing"><img src="https://avatars.githubusercontent.com/u/5097752?v=4&s=48" width="48" height="48" alt="imfing" title="imfing"/></a> <a href="https://github.com/jalehman"><img src="https://avatars.githubusercontent.com/u/550978?v=4&s=48" width="48" height="48" alt="jalehman" title="jalehman"/></a>
|
| 494 |
+
<a href="https://github.com/jarvis-medmatic"><img src="https://avatars.githubusercontent.com/u/252428873?v=4&s=48" width="48" height="48" alt="jarvis-medmatic" title="jarvis-medmatic"/></a> <a href="https://github.com/kkarimi"><img src="https://avatars.githubusercontent.com/u/875218?v=4&s=48" width="48" height="48" alt="kkarimi" title="kkarimi"/></a> <a href="https://github.com/mahmoudashraf93"><img src="https://avatars.githubusercontent.com/u/9130129?v=4&s=48" width="48" height="48" alt="mahmoudashraf93" title="mahmoudashraf93"/></a> <a href="https://github.com/pkrmf"><img src="https://avatars.githubusercontent.com/u/1714267?v=4&s=48" width="48" height="48" alt="pkrmf" title="pkrmf"/></a> <a href="https://github.com/RandyVentures"><img src="https://avatars.githubusercontent.com/u/149904821?v=4&s=48" width="48" height="48" alt="RandyVentures" title="RandyVentures"/></a> <a href="https://github.com/search?q=Ryan%20Lisse"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Ryan Lisse" title="Ryan Lisse"/></a> <a href="https://github.com/dougvk"><img src="https://avatars.githubusercontent.com/u/401660?v=4&s=48" width="48" height="48" alt="dougvk" title="dougvk"/></a> <a href="https://github.com/erikpr1994"><img src="https://avatars.githubusercontent.com/u/6299331?v=4&s=48" width="48" height="48" alt="erikpr1994" title="erikpr1994"/></a> <a href="https://github.com/search?q=Ghost"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Ghost" title="Ghost"/></a> <a href="https://github.com/jonasjancarik"><img src="https://avatars.githubusercontent.com/u/2459191?v=4&s=48" width="48" height="48" alt="jonasjancarik" title="jonasjancarik"/></a>
|
| 495 |
+
<a href="https://github.com/search?q=Keith%20the%20Silly%20Goose"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Keith the Silly Goose" title="Keith the Silly Goose"/></a> <a href="https://github.com/search?q=L36%20Server"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="L36 Server" title="L36 Server"/></a> <a href="https://github.com/search?q=Marc"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Marc" title="Marc"/></a> <a href="https://github.com/mitschabaude-bot"><img src="https://avatars.githubusercontent.com/u/247582884?v=4&s=48" width="48" height="48" alt="mitschabaude-bot" title="mitschabaude-bot"/></a> <a href="https://github.com/mkbehr"><img src="https://avatars.githubusercontent.com/u/1285?v=4&s=48" width="48" height="48" alt="mkbehr" title="mkbehr"/></a> <a href="https://github.com/neist"><img src="https://avatars.githubusercontent.com/u/1029724?v=4&s=48" width="48" height="48" alt="neist" title="neist"/></a> <a href="https://github.com/sibbl"><img src="https://avatars.githubusercontent.com/u/866535?v=4&s=48" width="48" height="48" alt="sibbl" title="sibbl"/></a> <a href="https://github.com/chrisrodz"><img src="https://avatars.githubusercontent.com/u/2967620?v=4&s=48" width="48" height="48" alt="chrisrodz" title="chrisrodz"/></a> <a href="https://github.com/search?q=Friederike%20Seiler"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Friederike Seiler" title="Friederike Seiler"/></a> <a href="https://github.com/gabriel-trigo"><img src="https://avatars.githubusercontent.com/u/38991125?v=4&s=48" width="48" height="48" alt="gabriel-trigo" title="gabriel-trigo"/></a>
|
| 496 |
+
<a href="https://github.com/Iamadig"><img src="https://avatars.githubusercontent.com/u/102129234?v=4&s=48" width="48" height="48" alt="iamadig" title="iamadig"/></a> <a href="https://github.com/jdrhyne"><img src="https://avatars.githubusercontent.com/u/7828464?v=4&s=48" width="48" height="48" alt="Jonathan D. Rhyne (DJ-D)" title="Jonathan D. Rhyne (DJ-D)"/></a> <a href="https://github.com/search?q=Joshua%20Mitchell"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Joshua Mitchell" title="Joshua Mitchell"/></a> <a href="https://github.com/search?q=Kit"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Kit" title="Kit"/></a> <a href="https://github.com/koala73"><img src="https://avatars.githubusercontent.com/u/996596?v=4&s=48" width="48" height="48" alt="koala73" title="koala73"/></a> <a href="https://github.com/manmal"><img src="https://avatars.githubusercontent.com/u/142797?v=4&s=48" width="48" height="48" alt="manmal" title="manmal"/></a> <a href="https://github.com/ogulcancelik"><img src="https://avatars.githubusercontent.com/u/7064011?v=4&s=48" width="48" height="48" alt="ogulcancelik" title="ogulcancelik"/></a> <a href="https://github.com/pasogott"><img src="https://avatars.githubusercontent.com/u/23458152?v=4&s=48" width="48" height="48" alt="pasogott" title="pasogott"/></a> <a href="https://github.com/petradonka"><img src="https://avatars.githubusercontent.com/u/7353770?v=4&s=48" width="48" height="48" alt="petradonka" title="petradonka"/></a> <a href="https://github.com/rubyrunsstuff"><img src="https://avatars.githubusercontent.com/u/246602379?v=4&s=48" width="48" height="48" alt="rubyrunsstuff" title="rubyrunsstuff"/></a>
|
| 497 |
+
<a href="https://github.com/siddhantjain"><img src="https://avatars.githubusercontent.com/u/4835232?v=4&s=48" width="48" height="48" alt="siddhantjain" title="siddhantjain"/></a> <a href="https://github.com/suminhthanh"><img src="https://avatars.githubusercontent.com/u/2907636?v=4&s=48" width="48" height="48" alt="suminhthanh" title="suminhthanh"/></a> <a href="https://github.com/svkozak"><img src="https://avatars.githubusercontent.com/u/31941359?v=4&s=48" width="48" height="48" alt="svkozak" title="svkozak"/></a> <a href="https://github.com/VACInc"><img src="https://avatars.githubusercontent.com/u/3279061?v=4&s=48" width="48" height="48" alt="VACInc" title="VACInc"/></a> <a href="https://github.com/wes-davis"><img src="https://avatars.githubusercontent.com/u/16506720?v=4&s=48" width="48" height="48" alt="wes-davis" title="wes-davis"/></a> <a href="https://github.com/zats"><img src="https://avatars.githubusercontent.com/u/2688806?v=4&s=48" width="48" height="48" alt="zats" title="zats"/></a> <a href="https://github.com/24601"><img src="https://avatars.githubusercontent.com/u/1157207?v=4&s=48" width="48" height="48" alt="24601" title="24601"/></a> <a href="https://github.com/adam91holt"><img src="https://avatars.githubusercontent.com/u/9592417?v=4&s=48" width="48" height="48" alt="adam91holt" title="adam91holt"/></a> <a href="https://github.com/ameno-"><img src="https://avatars.githubusercontent.com/u/2416135?v=4&s=48" width="48" height="48" alt="ameno-" title="ameno-"/></a> <a href="https://github.com/search?q=Chris%20Taylor"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Chris Taylor" title="Chris Taylor"/></a>
|
| 498 |
+
<a href="https://github.com/dguido"><img src="https://avatars.githubusercontent.com/u/294844?v=4&s=48" width="48" height="48" alt="dguido" title="dguido"/></a> <a href="https://github.com/djangonavarro220"><img src="https://avatars.githubusercontent.com/u/251162586?v=4&s=48" width="48" height="48" alt="Django Navarro" title="Django Navarro"/></a> <a href="https://github.com/evalexpr"><img src="https://avatars.githubusercontent.com/u/23485511?v=4&s=48" width="48" height="48" alt="evalexpr" title="evalexpr"/></a> <a href="https://github.com/henrino3"><img src="https://avatars.githubusercontent.com/u/4260288?v=4&s=48" width="48" height="48" alt="henrino3" title="henrino3"/></a> <a href="https://github.com/humanwritten"><img src="https://avatars.githubusercontent.com/u/206531610?v=4&s=48" width="48" height="48" alt="humanwritten" title="humanwritten"/></a> <a href="https://github.com/larlyssa"><img src="https://avatars.githubusercontent.com/u/13128869?v=4&s=48" width="48" height="48" alt="larlyssa" title="larlyssa"/></a> <a href="https://github.com/odysseus0"><img src="https://avatars.githubusercontent.com/u/8635094?v=4&s=48" width="48" height="48" alt="odysseus0" title="odysseus0"/></a> <a href="https://github.com/oswalpalash"><img src="https://avatars.githubusercontent.com/u/6431196?v=4&s=48" width="48" height="48" alt="oswalpalash" title="oswalpalash"/></a> <a href="https://github.com/pcty-nextgen-service-account"><img src="https://avatars.githubusercontent.com/u/112553441?v=4&s=48" width="48" height="48" alt="pcty-nextgen-service-account" title="pcty-nextgen-service-account"/></a> <a href="https://github.com/rmorse"><img src="https://avatars.githubusercontent.com/u/853547?v=4&s=48" width="48" height="48" alt="rmorse" title="rmorse"/></a>
|
| 499 |
+
<a href="https://github.com/Syhids"><img src="https://avatars.githubusercontent.com/u/671202?v=4&s=48" width="48" height="48" alt="Syhids" title="Syhids"/></a> <a href="https://github.com/search?q=Aaron%20Konyer"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Aaron Konyer" title="Aaron Konyer"/></a> <a href="https://github.com/aaronveklabs"><img src="https://avatars.githubusercontent.com/u/225997828?v=4&s=48" width="48" height="48" alt="aaronveklabs" title="aaronveklabs"/></a> <a href="https://github.com/andreabadesso"><img src="https://avatars.githubusercontent.com/u/3586068?v=4&s=48" width="48" height="48" alt="andreabadesso" title="andreabadesso"/></a> <a href="https://github.com/search?q=Andrii"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Andrii" title="Andrii"/></a> <a href="https://github.com/cash-echo-bot"><img src="https://avatars.githubusercontent.com/u/252747386?v=4&s=48" width="48" height="48" alt="cash-echo-bot" title="cash-echo-bot"/></a> <a href="https://github.com/search?q=Clawd"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Clawd" title="Clawd"/></a> <a href="https://github.com/search?q=ClawdFx"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="ClawdFx" title="ClawdFx"/></a> <a href="https://github.com/EnzeD"><img src="https://avatars.githubusercontent.com/u/9866900?v=4&s=48" width="48" height="48" alt="EnzeD" title="EnzeD"/></a> <a href="https://github.com/erik-agens"><img src="https://avatars.githubusercontent.com/u/80908960?v=4&s=48" width="48" height="48" alt="erik-agens" title="erik-agens"/></a>
|
| 500 |
+
<a href="https://github.com/Evizero"><img src="https://avatars.githubusercontent.com/u/10854026?v=4&s=48" width="48" height="48" alt="Evizero" title="Evizero"/></a> <a href="https://github.com/fcatuhe"><img src="https://avatars.githubusercontent.com/u/17382215?v=4&s=48" width="48" height="48" alt="fcatuhe" title="fcatuhe"/></a> <a href="https://github.com/itsjaydesu"><img src="https://avatars.githubusercontent.com/u/220390?v=4&s=48" width="48" height="48" alt="itsjaydesu" title="itsjaydesu"/></a> <a href="https://github.com/ivancasco"><img src="https://avatars.githubusercontent.com/u/2452858?v=4&s=48" width="48" height="48" alt="ivancasco" title="ivancasco"/></a> <a href="https://github.com/ivanrvpereira"><img src="https://avatars.githubusercontent.com/u/183991?v=4&s=48" width="48" height="48" alt="ivanrvpereira" title="ivanrvpereira"/></a> <a href="https://github.com/jayhickey"><img src="https://avatars.githubusercontent.com/u/1676460?v=4&s=48" width="48" height="48" alt="jayhickey" title="jayhickey"/></a> <a href="https://github.com/jeffersonwarrior"><img src="https://avatars.githubusercontent.com/u/89030989?v=4&s=48" width="48" height="48" alt="jeffersonwarrior" title="jeffersonwarrior"/></a> <a href="https://github.com/search?q=jeffersonwarrior"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="jeffersonwarrior" title="jeffersonwarrior"/></a> <a href="https://github.com/jverdi"><img src="https://avatars.githubusercontent.com/u/345050?v=4&s=48" width="48" height="48" alt="jverdi" title="jverdi"/></a> <a href="https://github.com/longmaba"><img src="https://avatars.githubusercontent.com/u/9361500?v=4&s=48" width="48" height="48" alt="longmaba" title="longmaba"/></a>
|
| 501 |
+
<a href="https://github.com/mickahouan"><img src="https://avatars.githubusercontent.com/u/31423109?v=4&s=48" width="48" height="48" alt="mickahouan" title="mickahouan"/></a> <a href="https://github.com/mjrussell"><img src="https://avatars.githubusercontent.com/u/1641895?v=4&s=48" width="48" height="48" alt="mjrussell" title="mjrussell"/></a> <a href="https://github.com/odnxe"><img src="https://avatars.githubusercontent.com/u/403141?v=4&s=48" width="48" height="48" alt="odnxe" title="odnxe"/></a> <a href="https://github.com/p6l-richard"><img src="https://avatars.githubusercontent.com/u/18185649?v=4&s=48" width="48" height="48" alt="p6l-richard" title="p6l-richard"/></a> <a href="https://github.com/philipp-spiess"><img src="https://avatars.githubusercontent.com/u/458591?v=4&s=48" width="48" height="48" alt="philipp-spiess" title="philipp-spiess"/></a> <a href="https://github.com/search?q=Pocket%20Clawd"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Pocket Clawd" title="Pocket Clawd"/></a> <a href="https://github.com/robaxelsen"><img src="https://avatars.githubusercontent.com/u/13132899?v=4&s=48" width="48" height="48" alt="robaxelsen" title="robaxelsen"/></a> <a href="https://github.com/search?q=Sash%20Catanzarite"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Sash Catanzarite" title="Sash Catanzarite"/></a> <a href="https://github.com/T5-AndyML"><img src="https://avatars.githubusercontent.com/u/22801233?v=4&s=48" width="48" height="48" alt="T5-AndyML" title="T5-AndyML"/></a> <a href="https://github.com/travisp"><img src="https://avatars.githubusercontent.com/u/165698?v=4&s=48" width="48" height="48" alt="travisp" title="travisp"/></a>
|
| 502 |
+
<a href="https://github.com/search?q=VAC"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="VAC" title="VAC"/></a> <a href="https://github.com/search?q=william%20arzt"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="william arzt" title="william arzt"/></a> <a href="https://github.com/zknicker"><img src="https://avatars.githubusercontent.com/u/1164085?v=4&s=48" width="48" height="48" alt="zknicker" title="zknicker"/></a> <a href="https://github.com/abhaymundhara"><img src="https://avatars.githubusercontent.com/u/62872231?v=4&s=48" width="48" height="48" alt="abhaymundhara" title="abhaymundhara"/></a> <a href="https://github.com/search?q=alejandro%20maza"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="alejandro maza" title="alejandro maza"/></a> <a href="https://github.com/Alex-Alaniz"><img src="https://avatars.githubusercontent.com/u/88956822?v=4&s=48" width="48" height="48" alt="Alex-Alaniz" title="Alex-Alaniz"/></a> <a href="https://github.com/alexstyl"><img src="https://avatars.githubusercontent.com/u/1665273?v=4&s=48" width="48" height="48" alt="alexstyl" title="alexstyl"/></a> <a href="https://github.com/andrewting19"><img src="https://avatars.githubusercontent.com/u/10536704?v=4&s=48" width="48" height="48" alt="andrewting19" title="andrewting19"/></a> <a href="https://github.com/anpoirier"><img src="https://avatars.githubusercontent.com/u/1245729?v=4&s=48" width="48" height="48" alt="anpoirier" title="anpoirier"/></a> <a href="https://github.com/arthyn"><img src="https://avatars.githubusercontent.com/u/5466421?v=4&s=48" width="48" height="48" alt="arthyn" title="arthyn"/></a>
|
| 503 |
+
<a href="https://github.com/Asleep123"><img src="https://avatars.githubusercontent.com/u/122379135?v=4&s=48" width="48" height="48" alt="Asleep123" title="Asleep123"/></a> <a href="https://github.com/bolismauro"><img src="https://avatars.githubusercontent.com/u/771999?v=4&s=48" width="48" height="48" alt="bolismauro" title="bolismauro"/></a> <a href="https://github.com/chenyuan99"><img src="https://avatars.githubusercontent.com/u/25518100?v=4&s=48" width="48" height="48" alt="chenyuan99" title="chenyuan99"/></a> <a href="https://github.com/search?q=Clawdbot%20Maintainers"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Clawdbot Maintainers" title="Clawdbot Maintainers"/></a> <a href="https://github.com/conhecendoia"><img src="https://avatars.githubusercontent.com/u/82890727?v=4&s=48" width="48" height="48" alt="conhecendoia" title="conhecendoia"/></a> <a href="https://github.com/dasilva333"><img src="https://avatars.githubusercontent.com/u/947827?v=4&s=48" width="48" height="48" alt="dasilva333" title="dasilva333"/></a> <a href="https://github.com/David-Marsh-Photo"><img src="https://avatars.githubusercontent.com/u/228404527?v=4&s=48" width="48" height="48" alt="David-Marsh-Photo" title="David-Marsh-Photo"/></a> <a href="https://github.com/search?q=Developer"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Developer" title="Developer"/></a> <a href="https://github.com/search?q=Dimitrios%20Ploutarchos"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Dimitrios Ploutarchos" title="Dimitrios Ploutarchos"/></a> <a href="https://github.com/search?q=Drake%20Thomsen"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Drake Thomsen" title="Drake Thomsen"/></a>
|
| 504 |
+
<a href="https://github.com/fal3"><img src="https://avatars.githubusercontent.com/u/6484295?v=4&s=48" width="48" height="48" alt="fal3" title="fal3"/></a> <a href="https://github.com/search?q=Felix%20Krause"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Felix Krause" title="Felix Krause"/></a> <a href="https://github.com/foeken"><img src="https://avatars.githubusercontent.com/u/13864?v=4&s=48" width="48" height="48" alt="foeken" title="foeken"/></a> <a href="https://github.com/search?q=ganghyun%20kim"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="ganghyun kim" title="ganghyun kim"/></a> <a href="https://github.com/grrowl"><img src="https://avatars.githubusercontent.com/u/907140?v=4&s=48" width="48" height="48" alt="grrowl" title="grrowl"/></a> <a href="https://github.com/gtsifrikas"><img src="https://avatars.githubusercontent.com/u/8904378?v=4&s=48" width="48" height="48" alt="gtsifrikas" title="gtsifrikas"/></a> <a href="https://github.com/HazAT"><img src="https://avatars.githubusercontent.com/u/363802?v=4&s=48" width="48" height="48" alt="HazAT" title="HazAT"/></a> <a href="https://github.com/hrdwdmrbl"><img src="https://avatars.githubusercontent.com/u/554881?v=4&s=48" width="48" height="48" alt="hrdwdmrbl" title="hrdwdmrbl"/></a> <a href="https://github.com/hugobarauna"><img src="https://avatars.githubusercontent.com/u/2719?v=4&s=48" width="48" height="48" alt="hugobarauna" title="hugobarauna"/></a> <a href="https://github.com/search?q=Jamie%20Openshaw"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Jamie Openshaw" title="Jamie Openshaw"/></a>
|
| 505 |
+
<a href="https://github.com/search?q=Jane"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Jane" title="Jane"/></a> <a href="https://github.com/search?q=Jarvis"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Jarvis" title="Jarvis"/></a> <a href="https://github.com/search?q=Jefferson%20Nunn"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Jefferson Nunn" title="Jefferson Nunn"/></a> <a href="https://github.com/kentaro"><img src="https://avatars.githubusercontent.com/u/3458?v=4&s=48" width="48" height="48" alt="kentaro" title="kentaro"/></a> <a href="https://github.com/search?q=Kevin%20Lin"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Kevin Lin" title="Kevin Lin"/></a> <a href="https://github.com/kitze"><img src="https://avatars.githubusercontent.com/u/1160594?v=4&s=48" width="48" height="48" alt="kitze" title="kitze"/></a> <a href="https://github.com/Kiwitwitter"><img src="https://avatars.githubusercontent.com/u/25277769?v=4&s=48" width="48" height="48" alt="Kiwitwitter" title="Kiwitwitter"/></a> <a href="https://github.com/levifig"><img src="https://avatars.githubusercontent.com/u/1605?v=4&s=48" width="48" height="48" alt="levifig" title="levifig"/></a> <a href="https://github.com/search?q=Lloyd"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Lloyd" title="Lloyd"/></a> <a href="https://github.com/loukotal"><img src="https://avatars.githubusercontent.com/u/18210858?v=4&s=48" width="48" height="48" alt="loukotal" title="loukotal"/></a>
|
| 506 |
+
<a href="https://github.com/louzhixian"><img src="https://avatars.githubusercontent.com/u/7994361?v=4&s=48" width="48" height="48" alt="louzhixian" title="louzhixian"/></a> <a href="https://github.com/martinpucik"><img src="https://avatars.githubusercontent.com/u/5503097?v=4&s=48" width="48" height="48" alt="martinpucik" title="martinpucik"/></a> <a href="https://github.com/search?q=Matt%20mini"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Matt mini" title="Matt mini"/></a> <a href="https://github.com/mertcicekci0"><img src="https://avatars.githubusercontent.com/u/179321902?v=4&s=48" width="48" height="48" alt="mertcicekci0" title="mertcicekci0"/></a> <a href="https://github.com/search?q=Miles"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Miles" title="Miles"/></a> <a href="https://github.com/mrdbstn"><img src="https://avatars.githubusercontent.com/u/58957632?v=4&s=48" width="48" height="48" alt="mrdbstn" title="mrdbstn"/></a> <a href="https://github.com/MSch"><img src="https://avatars.githubusercontent.com/u/7475?v=4&s=48" width="48" height="48" alt="MSch" title="MSch"/></a> <a href="https://github.com/search?q=Mustafa%20Tag%20Eldeen"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Mustafa Tag Eldeen" title="Mustafa Tag Eldeen"/></a> <a href="https://github.com/ndraiman"><img src="https://avatars.githubusercontent.com/u/12609607?v=4&s=48" width="48" height="48" alt="ndraiman" title="ndraiman"/></a> <a href="https://github.com/nexty5870"><img src="https://avatars.githubusercontent.com/u/3869659?v=4&s=48" width="48" height="48" alt="nexty5870" title="nexty5870"/></a>
|
| 507 |
+
<a href="https://github.com/Noctivoro"><img src="https://avatars.githubusercontent.com/u/183974570?v=4&s=48" width="48" height="48" alt="Noctivoro" title="Noctivoro"/></a> <a href="https://github.com/ppamment"><img src="https://avatars.githubusercontent.com/u/2122919?v=4&s=48" width="48" height="48" alt="ppamment" title="ppamment"/></a> <a href="https://github.com/prathamdby"><img src="https://avatars.githubusercontent.com/u/134331217?v=4&s=48" width="48" height="48" alt="prathamdby" title="prathamdby"/></a> <a href="https://github.com/ptn1411"><img src="https://avatars.githubusercontent.com/u/57529765?v=4&s=48" width="48" height="48" alt="ptn1411" title="ptn1411"/></a> <a href="https://github.com/reeltimeapps"><img src="https://avatars.githubusercontent.com/u/637338?v=4&s=48" width="48" height="48" alt="reeltimeapps" title="reeltimeapps"/></a> <a href="https://github.com/RLTCmpe"><img src="https://avatars.githubusercontent.com/u/10762242?v=4&s=48" width="48" height="48" alt="RLTCmpe" title="RLTCmpe"/></a> <a href="https://github.com/search?q=Rolf%20Fredheim"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Rolf Fredheim" title="Rolf Fredheim"/></a> <a href="https://github.com/search?q=Rony%20Kelner"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Rony Kelner" title="Rony Kelner"/></a> <a href="https://github.com/search?q=Samrat%20Jha"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Samrat Jha" title="Samrat Jha"/></a> <a href="https://github.com/senoldogann"><img src="https://avatars.githubusercontent.com/u/45736551?v=4&s=48" width="48" height="48" alt="senoldogann" title="senoldogann"/></a>
|
| 508 |
+
<a href="https://github.com/Seredeep"><img src="https://avatars.githubusercontent.com/u/22802816?v=4&s=48" width="48" height="48" alt="Seredeep" title="Seredeep"/></a> <a href="https://github.com/sergical"><img src="https://avatars.githubusercontent.com/u/3760543?v=4&s=48" width="48" height="48" alt="sergical" title="sergical"/></a> <a href="https://github.com/shiv19"><img src="https://avatars.githubusercontent.com/u/9407019?v=4&s=48" width="48" height="48" alt="shiv19" title="shiv19"/></a> <a href="https://github.com/shiyuanhai"><img src="https://avatars.githubusercontent.com/u/1187370?v=4&s=48" width="48" height="48" alt="shiyuanhai" title="shiyuanhai"/></a> <a href="https://github.com/siraht"><img src="https://avatars.githubusercontent.com/u/73152895?v=4&s=48" width="48" height="48" alt="siraht" title="siraht"/></a> <a href="https://github.com/snopoke"><img src="https://avatars.githubusercontent.com/u/249606?v=4&s=48" width="48" height="48" alt="snopoke" title="snopoke"/></a> <a href="https://github.com/Suksham-sharma"><img src="https://avatars.githubusercontent.com/u/94667656?v=4&s=48" width="48" height="48" alt="Suksham-sharma" title="Suksham-sharma"/></a> <a href="https://github.com/search?q=techboss"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="techboss" title="techboss"/></a> <a href="https://github.com/testingabc321"><img src="https://avatars.githubusercontent.com/u/8577388?v=4&s=48" width="48" height="48" alt="testingabc321" title="testingabc321"/></a> <a href="https://github.com/search?q=The%20Admiral"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="The Admiral" title="The Admiral"/></a>
|
| 509 |
+
<a href="https://github.com/thesash"><img src="https://avatars.githubusercontent.com/u/1166151?v=4&s=48" width="48" height="48" alt="thesash" title="thesash"/></a> <a href="https://github.com/search?q=Ubuntu"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Ubuntu" title="Ubuntu"/></a> <a href="https://github.com/voidserf"><img src="https://avatars.githubusercontent.com/u/477673?v=4&s=48" width="48" height="48" alt="voidserf" title="voidserf"/></a> <a href="https://github.com/search?q=Vultr-Clawd%20Admin"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Vultr-Clawd Admin" title="Vultr-Clawd Admin"/></a> <a href="https://github.com/search?q=Wimmie"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Wimmie" title="Wimmie"/></a> <a href="https://github.com/search?q=wolfred"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="wolfred" title="wolfred"/></a> <a href="https://github.com/wstock"><img src="https://avatars.githubusercontent.com/u/1394687?v=4&s=48" width="48" height="48" alt="wstock" title="wstock"/></a> <a href="https://github.com/yazinsai"><img src="https://avatars.githubusercontent.com/u/1846034?v=4&s=48" width="48" height="48" alt="yazinsai" title="yazinsai"/></a> <a href="https://github.com/search?q=ymat19"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="ymat19" title="ymat19"/></a> <a href="https://github.com/search?q=Zach%20Knickerbocker"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Zach Knickerbocker" title="Zach Knickerbocker"/></a>
|
| 510 |
+
<a href="https://github.com/0xJonHoldsCrypto"><img src="https://avatars.githubusercontent.com/u/81202085?v=4&s=48" width="48" height="48" alt="0xJonHoldsCrypto" title="0xJonHoldsCrypto"/></a> <a href="https://github.com/aaronn"><img src="https://avatars.githubusercontent.com/u/1653630?v=4&s=48" width="48" height="48" alt="aaronn" title="aaronn"/></a> <a href="https://github.com/Alphonse-arianee"><img src="https://avatars.githubusercontent.com/u/254457365?v=4&s=48" width="48" height="48" alt="Alphonse-arianee" title="Alphonse-arianee"/></a> <a href="https://github.com/atalovesyou"><img src="https://avatars.githubusercontent.com/u/3534502?v=4&s=48" width="48" height="48" alt="atalovesyou" title="atalovesyou"/></a> <a href="https://github.com/search?q=Azade"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Azade" title="Azade"/></a> <a href="https://github.com/carlulsoe"><img src="https://avatars.githubusercontent.com/u/34673973?v=4&s=48" width="48" height="48" alt="carlulsoe" title="carlulsoe"/></a> <a href="https://github.com/search?q=ddyo"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="ddyo" title="ddyo"/></a> <a href="https://github.com/search?q=Erik"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Erik" title="Erik"/></a> <a href="https://github.com/hougangdev"><img src="https://avatars.githubusercontent.com/u/105773686?v=4&s=48" width="48" height="48" alt="hougangdev" title="hougangdev"/></a> <a href="https://github.com/latitudeki5223"><img src="https://avatars.githubusercontent.com/u/119656367?v=4&s=48" width="48" height="48" alt="latitudeki5223" title="latitudeki5223"/></a>
|
| 511 |
+
<a href="https://github.com/search?q=Manuel%20Maly"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Manuel Maly" title="Manuel Maly"/></a> <a href="https://github.com/search?q=Mourad%20Boustani"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Mourad Boustani" title="Mourad Boustani"/></a> <a href="https://github.com/odrobnik"><img src="https://avatars.githubusercontent.com/u/333270?v=4&s=48" width="48" height="48" alt="odrobnik" title="odrobnik"/></a> <a href="https://github.com/pcty-nextgen-ios-builder"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="pcty-nextgen-ios-builder" title="pcty-nextgen-ios-builder"/></a> <a href="https://github.com/search?q=Quentin"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Quentin" title="Quentin"/></a> <a href="https://github.com/search?q=Randy%20Torres"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="Randy Torres" title="Randy Torres"/></a> <a href="https://github.com/rhjoh"><img src="https://avatars.githubusercontent.com/u/105699450?v=4&s=48" width="48" height="48" alt="rhjoh" title="rhjoh"/></a> <a href="https://github.com/ronak-guliani"><img src="https://avatars.githubusercontent.com/u/23518228?v=4&s=48" width="48" height="48" alt="ronak-guliani" title="ronak-guliani"/></a> <a href="https://github.com/search?q=William%20Stock"><img src="assets/avatar-placeholder.svg" width="48" height="48" alt="William Stock" title="William Stock"/></a>
|
| 512 |
+
</p>
|
SECURITY.md
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Security Policy
|
| 2 |
+
|
| 3 |
+
If you believe you've found a security issue in Moltbot, please report it privately.
|
| 4 |
+
|
| 5 |
+
## Reporting
|
| 6 |
+
|
| 7 |
+
- Email: `steipete@gmail.com`
|
| 8 |
+
- What to include: reproduction steps, impact assessment, and (if possible) a minimal PoC.
|
| 9 |
+
|
| 10 |
+
## Operational Guidance
|
| 11 |
+
|
| 12 |
+
For threat model + hardening guidance (including `moltbot security audit --deep` and `--fix`), see:
|
| 13 |
+
|
| 14 |
+
- `https://docs.molt.bot/gateway/security`
|
| 15 |
+
|
| 16 |
+
### Web Interface Safety
|
| 17 |
+
|
| 18 |
+
Moltbot's web interface is intended for local use only. Do **not** bind it to the public internet; it is not hardened for public exposure.
|
| 19 |
+
|
| 20 |
+
## Runtime Requirements
|
| 21 |
+
|
| 22 |
+
### Node.js Version
|
| 23 |
+
|
| 24 |
+
Moltbot requires **Node.js 22.12.0 or later** (LTS). This version includes important security patches:
|
| 25 |
+
|
| 26 |
+
- CVE-2025-59466: async_hooks DoS vulnerability
|
| 27 |
+
- CVE-2026-21636: Permission model bypass vulnerability
|
| 28 |
+
|
| 29 |
+
Verify your Node.js version:
|
| 30 |
+
|
| 31 |
+
```bash
|
| 32 |
+
node --version # Should be v22.12.0 or later
|
| 33 |
+
```
|
| 34 |
+
|
| 35 |
+
### Docker Security
|
| 36 |
+
|
| 37 |
+
When running Moltbot in Docker:
|
| 38 |
+
|
| 39 |
+
1. The official image runs as a non-root user (`node`) for reduced attack surface
|
| 40 |
+
2. Use `--read-only` flag when possible for additional filesystem protection
|
| 41 |
+
3. Limit container capabilities with `--cap-drop=ALL`
|
| 42 |
+
|
| 43 |
+
Example secure Docker run:
|
| 44 |
+
|
| 45 |
+
```bash
|
| 46 |
+
docker run --read-only --cap-drop=ALL \
|
| 47 |
+
-v moltbot-data:/app/data \
|
| 48 |
+
moltbot/moltbot:latest
|
| 49 |
+
```
|
| 50 |
+
|
| 51 |
+
## Security Scanning
|
| 52 |
+
|
| 53 |
+
This project uses `detect-secrets` for automated secret detection in CI/CD.
|
| 54 |
+
See `.detect-secrets.cfg` for configuration and `.secrets.baseline` for the baseline.
|
| 55 |
+
|
| 56 |
+
Run locally:
|
| 57 |
+
|
| 58 |
+
```bash
|
| 59 |
+
pip install detect-secrets==1.5.0
|
| 60 |
+
detect-secrets scan --baseline .secrets.baseline
|
| 61 |
+
```
|
Swabble/.github/workflows/ci.yml
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
name: CI
|
| 2 |
+
|
| 3 |
+
on:
|
| 4 |
+
push:
|
| 5 |
+
branches: [main]
|
| 6 |
+
pull_request:
|
| 7 |
+
|
| 8 |
+
jobs:
|
| 9 |
+
build-and-test:
|
| 10 |
+
runs-on: macos-latest
|
| 11 |
+
defaults:
|
| 12 |
+
run:
|
| 13 |
+
shell: bash
|
| 14 |
+
working-directory: swabble
|
| 15 |
+
steps:
|
| 16 |
+
- name: Checkout swabble
|
| 17 |
+
uses: actions/checkout@v4
|
| 18 |
+
with:
|
| 19 |
+
path: swabble
|
| 20 |
+
|
| 21 |
+
- name: Select Xcode 26.1 (prefer 26.1.1)
|
| 22 |
+
run: |
|
| 23 |
+
set -euo pipefail
|
| 24 |
+
# pick the newest installed 26.1.x, fallback to newest 26.x
|
| 25 |
+
CANDIDATE="$(ls -d /Applications/Xcode_26.1*.app 2>/dev/null | sort -V | tail -1 || true)"
|
| 26 |
+
if [[ -z "$CANDIDATE" ]]; then
|
| 27 |
+
CANDIDATE="$(ls -d /Applications/Xcode_26*.app 2>/dev/null | sort -V | tail -1 || true)"
|
| 28 |
+
fi
|
| 29 |
+
if [[ -z "$CANDIDATE" ]]; then
|
| 30 |
+
echo "No Xcode 26.x found on runner" >&2
|
| 31 |
+
exit 1
|
| 32 |
+
fi
|
| 33 |
+
echo "Selecting $CANDIDATE"
|
| 34 |
+
sudo xcode-select -s "$CANDIDATE"
|
| 35 |
+
xcodebuild -version
|
| 36 |
+
|
| 37 |
+
- name: Show Swift version
|
| 38 |
+
run: swift --version
|
| 39 |
+
|
| 40 |
+
- name: Install tooling
|
| 41 |
+
run: |
|
| 42 |
+
brew update
|
| 43 |
+
brew install swiftlint swiftformat
|
| 44 |
+
|
| 45 |
+
- name: Format check
|
| 46 |
+
run: |
|
| 47 |
+
./scripts/format.sh
|
| 48 |
+
git diff --exit-code
|
| 49 |
+
|
| 50 |
+
- name: Lint
|
| 51 |
+
run: ./scripts/lint.sh
|
| 52 |
+
|
| 53 |
+
- name: Test
|
| 54 |
+
run: swift test --parallel
|
Swabble/.gitignore
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# macOS
|
| 2 |
+
.DS_Store
|
| 3 |
+
|
| 4 |
+
# SwiftPM / Build
|
| 5 |
+
/.build
|
| 6 |
+
/.swiftpm
|
| 7 |
+
/DerivedData
|
| 8 |
+
xcuserdata/
|
| 9 |
+
*.xcuserstate
|
| 10 |
+
|
| 11 |
+
# Editors
|
| 12 |
+
/.vscode
|
| 13 |
+
.idea/
|
| 14 |
+
|
| 15 |
+
# Xcode artifacts
|
| 16 |
+
*.hmap
|
| 17 |
+
*.ipa
|
| 18 |
+
*.dSYM.zip
|
| 19 |
+
*.dSYM
|
| 20 |
+
|
| 21 |
+
# Playgrounds
|
| 22 |
+
*.xcplayground
|
| 23 |
+
playground.xcworkspace
|
| 24 |
+
timeline.xctimeline
|
| 25 |
+
|
| 26 |
+
# Carthage
|
| 27 |
+
Carthage/Build/
|
| 28 |
+
|
| 29 |
+
# fastlane
|
| 30 |
+
fastlane/report.xml
|
| 31 |
+
fastlane/Preview.html
|
| 32 |
+
fastlane/screenshots/**/*.png
|
| 33 |
+
fastlane/test_output
|
Swabble/.swiftformat
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
--swiftversion 6.2
|
| 2 |
+
--indent 4
|
| 3 |
+
--maxwidth 120
|
| 4 |
+
--wraparguments before-first
|
| 5 |
+
--wrapcollections before-first
|
| 6 |
+
--stripunusedargs closure-only
|
| 7 |
+
--self remove
|
| 8 |
+
--header ""
|
Swabble/.swiftlint.yml
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# SwiftLint for swabble
|
| 2 |
+
included:
|
| 3 |
+
- Sources
|
| 4 |
+
excluded:
|
| 5 |
+
- .build
|
| 6 |
+
- DerivedData
|
| 7 |
+
- "**/.swiftpm"
|
| 8 |
+
- "**/.build"
|
| 9 |
+
- "**/DerivedData"
|
| 10 |
+
- "**/.DS_Store"
|
| 11 |
+
opt_in_rules:
|
| 12 |
+
- array_init
|
| 13 |
+
- closure_spacing
|
| 14 |
+
- explicit_init
|
| 15 |
+
- fatal_error_message
|
| 16 |
+
- first_where
|
| 17 |
+
- joined_default_parameter
|
| 18 |
+
- last_where
|
| 19 |
+
- literal_expression_end_indentation
|
| 20 |
+
- multiline_arguments
|
| 21 |
+
- multiline_parameters
|
| 22 |
+
- operator_usage_whitespace
|
| 23 |
+
- redundant_nil_coalescing
|
| 24 |
+
- sorted_first_last
|
| 25 |
+
- switch_case_alignment
|
| 26 |
+
- vertical_parameter_alignment_on_call
|
| 27 |
+
- vertical_whitespace_opening_braces
|
| 28 |
+
- vertical_whitespace_closing_braces
|
| 29 |
+
|
| 30 |
+
disabled_rules:
|
| 31 |
+
- trailing_whitespace
|
| 32 |
+
- trailing_newline
|
| 33 |
+
- indentation_width
|
| 34 |
+
- identifier_name
|
| 35 |
+
- explicit_self
|
| 36 |
+
- file_header
|
| 37 |
+
- todo
|
| 38 |
+
|
| 39 |
+
line_length:
|
| 40 |
+
warning: 140
|
| 41 |
+
error: 180
|
| 42 |
+
|
| 43 |
+
reporter: "xcode"
|
Swabble/CHANGELOG.md
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Changelog
|
| 2 |
+
|
| 3 |
+
## 0.2.0 — 2025-12-23
|
| 4 |
+
|
| 5 |
+
### Highlights
|
| 6 |
+
- Added `SwabbleKit` (multi-platform wake-word gate utilities with segment-aware gap detection).
|
| 7 |
+
- Swabble package now supports iOS + macOS consumers; CLI remains macOS 26-only.
|
| 8 |
+
|
| 9 |
+
### Changes
|
| 10 |
+
- CLI wake-word matching/stripping routed through `SwabbleKit` helpers.
|
| 11 |
+
- Speech pipeline types now explicitly gated to macOS 26 / iOS 26 availability.
|
Swabble/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
MIT License
|
| 2 |
+
|
| 3 |
+
Copyright (c) 2025 Peter Steinberger
|
| 4 |
+
|
| 5 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
| 6 |
+
of this software and associated documentation files (the "Software"), to deal
|
| 7 |
+
in the Software without restriction, including without limitation the rights
|
| 8 |
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
| 9 |
+
copies of the Software, and to permit persons to whom the Software is
|
| 10 |
+
furnished to do so, subject to the following conditions:
|
| 11 |
+
|
| 12 |
+
The above copyright notice and this permission notice shall be included in all
|
| 13 |
+
copies or substantial portions of the Software.
|
| 14 |
+
|
| 15 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
| 16 |
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
| 17 |
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
| 18 |
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
| 19 |
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
| 20 |
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
| 21 |
+
SOFTWARE.
|
Swabble/Package.resolved
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"originHash" : "c0677e232394b5f6b0191b6dbb5bae553d55264f65ae725cd03a8ffdfda9cdd3",
|
| 3 |
+
"pins" : [
|
| 4 |
+
{
|
| 5 |
+
"identity" : "commander",
|
| 6 |
+
"kind" : "remoteSourceControl",
|
| 7 |
+
"location" : "https://github.com/steipete/Commander.git",
|
| 8 |
+
"state" : {
|
| 9 |
+
"revision" : "9e349575c8e3c6745e81fe19e5bb5efa01b078ce",
|
| 10 |
+
"version" : "0.2.1"
|
| 11 |
+
}
|
| 12 |
+
},
|
| 13 |
+
{
|
| 14 |
+
"identity" : "swift-syntax",
|
| 15 |
+
"kind" : "remoteSourceControl",
|
| 16 |
+
"location" : "https://github.com/swiftlang/swift-syntax.git",
|
| 17 |
+
"state" : {
|
| 18 |
+
"revision" : "0687f71944021d616d34d922343dcef086855920",
|
| 19 |
+
"version" : "600.0.1"
|
| 20 |
+
}
|
| 21 |
+
},
|
| 22 |
+
{
|
| 23 |
+
"identity" : "swift-testing",
|
| 24 |
+
"kind" : "remoteSourceControl",
|
| 25 |
+
"location" : "https://github.com/apple/swift-testing",
|
| 26 |
+
"state" : {
|
| 27 |
+
"revision" : "399f76dcd91e4c688ca2301fa24a8cc6d9927211",
|
| 28 |
+
"version" : "0.99.0"
|
| 29 |
+
}
|
| 30 |
+
}
|
| 31 |
+
],
|
| 32 |
+
"version" : 3
|
| 33 |
+
}
|
Swabble/Package.swift
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// swift-tools-version: 6.2
|
| 2 |
+
import PackageDescription
|
| 3 |
+
|
| 4 |
+
let package = Package(
|
| 5 |
+
name: "swabble",
|
| 6 |
+
platforms: [
|
| 7 |
+
.macOS(.v15),
|
| 8 |
+
.iOS(.v17),
|
| 9 |
+
],
|
| 10 |
+
products: [
|
| 11 |
+
.library(name: "Swabble", targets: ["Swabble"]),
|
| 12 |
+
.library(name: "SwabbleKit", targets: ["SwabbleKit"]),
|
| 13 |
+
.executable(name: "swabble", targets: ["SwabbleCLI"]),
|
| 14 |
+
],
|
| 15 |
+
dependencies: [
|
| 16 |
+
.package(url: "https://github.com/steipete/Commander.git", exact: "0.2.1"),
|
| 17 |
+
.package(url: "https://github.com/apple/swift-testing", from: "0.99.0"),
|
| 18 |
+
],
|
| 19 |
+
targets: [
|
| 20 |
+
.target(
|
| 21 |
+
name: "Swabble",
|
| 22 |
+
path: "Sources/SwabbleCore",
|
| 23 |
+
swiftSettings: []),
|
| 24 |
+
.target(
|
| 25 |
+
name: "SwabbleKit",
|
| 26 |
+
path: "Sources/SwabbleKit",
|
| 27 |
+
swiftSettings: [
|
| 28 |
+
.enableUpcomingFeature("StrictConcurrency"),
|
| 29 |
+
]),
|
| 30 |
+
.executableTarget(
|
| 31 |
+
name: "SwabbleCLI",
|
| 32 |
+
dependencies: [
|
| 33 |
+
"Swabble",
|
| 34 |
+
"SwabbleKit",
|
| 35 |
+
.product(name: "Commander", package: "Commander"),
|
| 36 |
+
],
|
| 37 |
+
path: "Sources/swabble"),
|
| 38 |
+
.testTarget(
|
| 39 |
+
name: "SwabbleKitTests",
|
| 40 |
+
dependencies: [
|
| 41 |
+
"SwabbleKit",
|
| 42 |
+
.product(name: "Testing", package: "swift-testing"),
|
| 43 |
+
],
|
| 44 |
+
swiftSettings: [
|
| 45 |
+
.enableUpcomingFeature("StrictConcurrency"),
|
| 46 |
+
.enableExperimentalFeature("SwiftTesting"),
|
| 47 |
+
]),
|
| 48 |
+
.testTarget(
|
| 49 |
+
name: "swabbleTests",
|
| 50 |
+
dependencies: [
|
| 51 |
+
"Swabble",
|
| 52 |
+
.product(name: "Testing", package: "swift-testing"),
|
| 53 |
+
]),
|
| 54 |
+
],
|
| 55 |
+
swiftLanguageModes: [.v6])
|
Swabble/README.md
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# 🎙️ swabble — Speech.framework wake-word hook daemon (macOS 26)
|
| 2 |
+
|
| 3 |
+
swabble is a Swift 6.2 wake-word hook daemon. The CLI targets macOS 26 (SpeechAnalyzer + SpeechTranscriber). The shared `SwabbleKit` target is multi-platform and exposes wake-word gating utilities for iOS/macOS apps.
|
| 4 |
+
|
| 5 |
+
- **Local-only**: Speech.framework on-device models; zero network usage.
|
| 6 |
+
- **Wake word**: Default `clawd` (aliases `claude`), optional `--no-wake` bypass.
|
| 7 |
+
- **SwabbleKit**: Shared wake gate utilities (gap-based gating when you provide speech segments).
|
| 8 |
+
- **Hooks**: Run any command with prefix/env, cooldown, min_chars, timeout.
|
| 9 |
+
- **Services**: launchd helper stubs for start/stop/install.
|
| 10 |
+
- **File transcribe**: TXT or SRT with time ranges (using AttributedString splits).
|
| 11 |
+
|
| 12 |
+
## Quick start
|
| 13 |
+
```bash
|
| 14 |
+
# Install deps
|
| 15 |
+
brew install swiftformat swiftlint
|
| 16 |
+
|
| 17 |
+
# Build
|
| 18 |
+
swift build
|
| 19 |
+
|
| 20 |
+
# Write default config (~/.config/swabble/config.json)
|
| 21 |
+
swift run swabble setup
|
| 22 |
+
|
| 23 |
+
# Run foreground daemon
|
| 24 |
+
swift run swabble serve
|
| 25 |
+
|
| 26 |
+
# Test your hook
|
| 27 |
+
swift run swabble test-hook "hello world"
|
| 28 |
+
|
| 29 |
+
# Transcribe a file to SRT
|
| 30 |
+
swift run swabble transcribe /path/to/audio.m4a --format srt --output out.srt
|
| 31 |
+
```
|
| 32 |
+
|
| 33 |
+
## Use as a library
|
| 34 |
+
Add swabble as a SwiftPM dependency and import the `Swabble` or `SwabbleKit` product:
|
| 35 |
+
|
| 36 |
+
```swift
|
| 37 |
+
// Package.swift
|
| 38 |
+
dependencies: [
|
| 39 |
+
.package(url: "https://github.com/steipete/swabble.git", branch: "main"),
|
| 40 |
+
],
|
| 41 |
+
targets: [
|
| 42 |
+
.target(name: "MyApp", dependencies: [
|
| 43 |
+
.product(name: "Swabble", package: "swabble"), // Speech pipeline (macOS 26+ / iOS 26+)
|
| 44 |
+
.product(name: "SwabbleKit", package: "swabble"), // Wake-word gate utilities (iOS 17+ / macOS 15+)
|
| 45 |
+
]),
|
| 46 |
+
]
|
| 47 |
+
```
|
| 48 |
+
|
| 49 |
+
## CLI
|
| 50 |
+
- `serve` — foreground loop (mic → wake → hook)
|
| 51 |
+
- `transcribe <file>` — offline transcription (txt|srt)
|
| 52 |
+
- `test-hook "text"` — invoke configured hook
|
| 53 |
+
- `mic list|set <index>` — enumerate/select input device
|
| 54 |
+
- `setup` — write default config JSON
|
| 55 |
+
- `doctor` — check Speech auth & device availability
|
| 56 |
+
- `health` — prints `ok`
|
| 57 |
+
- `tail-log` — last 10 transcripts
|
| 58 |
+
- `status` — show wake state + recent transcripts
|
| 59 |
+
- `service install|uninstall|status` — user launchd plist (stub: prints launchctl commands)
|
| 60 |
+
- `start|stop|restart` — placeholders until full launchd wiring
|
| 61 |
+
|
| 62 |
+
All commands accept Commander runtime flags (`-v/--verbose`, `--json-output`, `--log-level`), plus `--config` where applicable.
|
| 63 |
+
|
| 64 |
+
## Config
|
| 65 |
+
`~/.config/swabble/config.json` (auto-created by `setup`):
|
| 66 |
+
```json
|
| 67 |
+
{
|
| 68 |
+
"audio": {"deviceName": "", "deviceIndex": -1, "sampleRate": 16000, "channels": 1},
|
| 69 |
+
"wake": {"enabled": true, "word": "clawd", "aliases": ["claude"]},
|
| 70 |
+
"hook": {
|
| 71 |
+
"command": "",
|
| 72 |
+
"args": [],
|
| 73 |
+
"prefix": "Voice swabble from ${hostname}: ",
|
| 74 |
+
"cooldownSeconds": 1,
|
| 75 |
+
"minCharacters": 24,
|
| 76 |
+
"timeoutSeconds": 5,
|
| 77 |
+
"env": {}
|
| 78 |
+
},
|
| 79 |
+
"logging": {"level": "info", "format": "text"},
|
| 80 |
+
"transcripts": {"enabled": true, "maxEntries": 50},
|
| 81 |
+
"speech": {"localeIdentifier": "en_US", "etiquetteReplacements": false}
|
| 82 |
+
}
|
| 83 |
+
```
|
| 84 |
+
|
| 85 |
+
- Config path override: `--config /path/to/config.json` on relevant commands.
|
| 86 |
+
- Transcripts persist to `~/Library/Application Support/swabble/transcripts.log`.
|
| 87 |
+
|
| 88 |
+
## Hook protocol
|
| 89 |
+
When a wake-gated transcript passes min_chars & cooldown, swabble runs:
|
| 90 |
+
```
|
| 91 |
+
<command> <args...> "<prefix><text>"
|
| 92 |
+
```
|
| 93 |
+
Environment variables:
|
| 94 |
+
- `SWABBLE_TEXT` — stripped transcript (wake word removed)
|
| 95 |
+
- `SWABBLE_PREFIX` — rendered prefix (hostname substituted)
|
| 96 |
+
- plus any `hook.env` key/values
|
| 97 |
+
|
| 98 |
+
## Speech pipeline
|
| 99 |
+
- `AVAudioEngine` tap → `BufferConverter` → `AnalyzerInput` → `SpeechAnalyzer` with a `SpeechTranscriber` module.
|
| 100 |
+
- Requests volatile + final results; the CLI uses text-only wake gating today.
|
| 101 |
+
- Authorization requested at first start; requires macOS 26 + new Speech.framework APIs.
|
| 102 |
+
|
| 103 |
+
## Development
|
| 104 |
+
- Format: `./scripts/format.sh` (uses local `.swiftformat`)
|
| 105 |
+
- Lint: `./scripts/lint.sh` (uses local `.swiftlint.yml`)
|
| 106 |
+
- Tests: `swift test` (uses swift-testing package)
|
| 107 |
+
|
| 108 |
+
## Roadmap
|
| 109 |
+
- launchd control (load/bootout, PID + status socket)
|
| 110 |
+
- JSON logging + PII redaction toggle
|
| 111 |
+
- Stronger wake-word detection and control socket status/health
|
Swabble/Sources/SwabbleCore/Config/Config.swift
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import Foundation
|
| 2 |
+
|
| 3 |
+
public struct SwabbleConfig: Codable, Sendable {
|
| 4 |
+
public struct Audio: Codable, Sendable {
|
| 5 |
+
public var deviceName: String = ""
|
| 6 |
+
public var deviceIndex: Int = -1
|
| 7 |
+
public var sampleRate: Double = 16000
|
| 8 |
+
public var channels: Int = 1
|
| 9 |
+
}
|
| 10 |
+
|
| 11 |
+
public struct Wake: Codable, Sendable {
|
| 12 |
+
public var enabled: Bool = true
|
| 13 |
+
public var word: String = "clawd"
|
| 14 |
+
public var aliases: [String] = ["claude"]
|
| 15 |
+
}
|
| 16 |
+
|
| 17 |
+
public struct Hook: Codable, Sendable {
|
| 18 |
+
public var command: String = ""
|
| 19 |
+
public var args: [String] = []
|
| 20 |
+
public var prefix: String = "Voice swabble from ${hostname}: "
|
| 21 |
+
public var cooldownSeconds: Double = 1
|
| 22 |
+
public var minCharacters: Int = 24
|
| 23 |
+
public var timeoutSeconds: Double = 5
|
| 24 |
+
public var env: [String: String] = [:]
|
| 25 |
+
}
|
| 26 |
+
|
| 27 |
+
public struct Logging: Codable, Sendable {
|
| 28 |
+
public var level: String = "info"
|
| 29 |
+
public var format: String = "text" // text|json placeholder
|
| 30 |
+
}
|
| 31 |
+
|
| 32 |
+
public struct Transcripts: Codable, Sendable {
|
| 33 |
+
public var enabled: Bool = true
|
| 34 |
+
public var maxEntries: Int = 50
|
| 35 |
+
}
|
| 36 |
+
|
| 37 |
+
public struct Speech: Codable, Sendable {
|
| 38 |
+
public var localeIdentifier: String = Locale.current.identifier
|
| 39 |
+
public var etiquetteReplacements: Bool = false
|
| 40 |
+
}
|
| 41 |
+
|
| 42 |
+
public var audio = Audio()
|
| 43 |
+
public var wake = Wake()
|
| 44 |
+
public var hook = Hook()
|
| 45 |
+
public var logging = Logging()
|
| 46 |
+
public var transcripts = Transcripts()
|
| 47 |
+
public var speech = Speech()
|
| 48 |
+
|
| 49 |
+
public static let defaultPath = FileManager.default
|
| 50 |
+
.homeDirectoryForCurrentUser
|
| 51 |
+
.appendingPathComponent(".config/swabble/config.json")
|
| 52 |
+
|
| 53 |
+
public init() {}
|
| 54 |
+
}
|
| 55 |
+
|
| 56 |
+
public enum ConfigError: Error {
|
| 57 |
+
case missingConfig
|
| 58 |
+
}
|
| 59 |
+
|
| 60 |
+
public enum ConfigLoader {
|
| 61 |
+
public static func load(at path: URL?) throws -> SwabbleConfig {
|
| 62 |
+
let url = path ?? SwabbleConfig.defaultPath
|
| 63 |
+
if !FileManager.default.fileExists(atPath: url.path) {
|
| 64 |
+
throw ConfigError.missingConfig
|
| 65 |
+
}
|
| 66 |
+
let data = try Data(contentsOf: url)
|
| 67 |
+
return try JSONDecoder().decode(SwabbleConfig.self, from: data)
|
| 68 |
+
}
|
| 69 |
+
|
| 70 |
+
public static func save(_ config: SwabbleConfig, at path: URL?) throws {
|
| 71 |
+
let url = path ?? SwabbleConfig.defaultPath
|
| 72 |
+
let dir = url.deletingLastPathComponent()
|
| 73 |
+
try FileManager.default.createDirectory(at: dir, withIntermediateDirectories: true)
|
| 74 |
+
let data = try JSONEncoder().encode(config)
|
| 75 |
+
try data.write(to: url)
|
| 76 |
+
}
|
| 77 |
+
}
|
Swabble/Sources/SwabbleCore/Hooks/HookExecutor.swift
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import Foundation
|
| 2 |
+
|
| 3 |
+
public struct HookJob: Sendable {
|
| 4 |
+
public let text: String
|
| 5 |
+
public let timestamp: Date
|
| 6 |
+
|
| 7 |
+
public init(text: String, timestamp: Date) {
|
| 8 |
+
self.text = text
|
| 9 |
+
self.timestamp = timestamp
|
| 10 |
+
}
|
| 11 |
+
}
|
| 12 |
+
|
| 13 |
+
public actor HookExecutor {
|
| 14 |
+
private let config: SwabbleConfig
|
| 15 |
+
private var lastRun: Date?
|
| 16 |
+
private let hostname: String
|
| 17 |
+
|
| 18 |
+
public init(config: SwabbleConfig) {
|
| 19 |
+
self.config = config
|
| 20 |
+
hostname = Host.current().localizedName ?? "host"
|
| 21 |
+
}
|
| 22 |
+
|
| 23 |
+
public func shouldRun() -> Bool {
|
| 24 |
+
guard config.hook.cooldownSeconds > 0 else { return true }
|
| 25 |
+
if let lastRun, Date().timeIntervalSince(lastRun) < config.hook.cooldownSeconds {
|
| 26 |
+
return false
|
| 27 |
+
}
|
| 28 |
+
return true
|
| 29 |
+
}
|
| 30 |
+
|
| 31 |
+
public func run(job: HookJob) async throws {
|
| 32 |
+
guard shouldRun() else { return }
|
| 33 |
+
guard !config.hook.command.isEmpty else { throw NSError(
|
| 34 |
+
domain: "Hook",
|
| 35 |
+
code: 1,
|
| 36 |
+
userInfo: [NSLocalizedDescriptionKey: "hook command not set"]) }
|
| 37 |
+
|
| 38 |
+
let prefix = config.hook.prefix.replacingOccurrences(of: "${hostname}", with: hostname)
|
| 39 |
+
let payload = prefix + job.text
|
| 40 |
+
|
| 41 |
+
let process = Process()
|
| 42 |
+
process.executableURL = URL(fileURLWithPath: config.hook.command)
|
| 43 |
+
process.arguments = config.hook.args + [payload]
|
| 44 |
+
|
| 45 |
+
var env = ProcessInfo.processInfo.environment
|
| 46 |
+
env["SWABBLE_TEXT"] = job.text
|
| 47 |
+
env["SWABBLE_PREFIX"] = prefix
|
| 48 |
+
for (k, v) in config.hook.env {
|
| 49 |
+
env[k] = v
|
| 50 |
+
}
|
| 51 |
+
process.environment = env
|
| 52 |
+
|
| 53 |
+
let pipe = Pipe()
|
| 54 |
+
process.standardOutput = pipe
|
| 55 |
+
process.standardError = pipe
|
| 56 |
+
|
| 57 |
+
try process.run()
|
| 58 |
+
|
| 59 |
+
let timeoutNanos = UInt64(max(config.hook.timeoutSeconds, 0.1) * 1_000_000_000)
|
| 60 |
+
try await withThrowingTaskGroup(of: Void.self) { group in
|
| 61 |
+
group.addTask {
|
| 62 |
+
process.waitUntilExit()
|
| 63 |
+
}
|
| 64 |
+
group.addTask {
|
| 65 |
+
try await Task.sleep(nanoseconds: timeoutNanos)
|
| 66 |
+
if process.isRunning {
|
| 67 |
+
process.terminate()
|
| 68 |
+
}
|
| 69 |
+
}
|
| 70 |
+
try await group.next()
|
| 71 |
+
group.cancelAll()
|
| 72 |
+
}
|
| 73 |
+
lastRun = Date()
|
| 74 |
+
}
|
| 75 |
+
}
|