chore: purge warelay references
This commit is contained in:
12
CHANGELOG.md
12
CHANGELOG.md
@@ -23,7 +23,7 @@
|
|||||||
## 1.4.1 — 2025-12-04
|
## 1.4.1 — 2025-12-04
|
||||||
|
|
||||||
### Changes
|
### Changes
|
||||||
- Added `warelay agent` CLI command to talk directly to the configured agent using existing session handling (no WhatsApp send), with JSON output and delivery option.
|
- Added `clawdis agent` CLI command to talk directly to the configured agent using existing session handling (no WhatsApp send), with JSON output and delivery option.
|
||||||
- `/new` reset trigger now works even when inbound messages have timestamp prefixes (e.g., `[Dec 4 17:35]`).
|
- `/new` reset trigger now works even when inbound messages have timestamp prefixes (e.g., `[Dec 4 17:35]`).
|
||||||
- WhatsApp mention parsing accepts nullable arrays and flattens safely to avoid missed mentions.
|
- WhatsApp mention parsing accepts nullable arrays and flattens safely to avoid missed mentions.
|
||||||
|
|
||||||
@@ -31,7 +31,7 @@
|
|||||||
|
|
||||||
### Highlights
|
### Highlights
|
||||||
- **Thinking directives & state:** `/t|/think|/thinking <level>` (aliases off|minimal|low|medium|high|max/highest). Inline applies to that message; directive-only message pins the level for the session; `/think:off` clears. Resolution: inline > session override > `inbound.reply.thinkingDefault` > off. Pi/Tau get `--thinking <level>` (except off); other agents append cue words (`think` → `think hard` → `think harder` → `ultrathink`). Heartbeat probe uses `HEARTBEAT /think:high`.
|
- **Thinking directives & state:** `/t|/think|/thinking <level>` (aliases off|minimal|low|medium|high|max/highest). Inline applies to that message; directive-only message pins the level for the session; `/think:off` clears. Resolution: inline > session override > `inbound.reply.thinkingDefault` > off. Pi/Tau get `--thinking <level>` (except off); other agents append cue words (`think` → `think hard` → `think harder` → `ultrathink`). Heartbeat probe uses `HEARTBEAT /think:high`.
|
||||||
- **Group chats (web provider):** Warelay now fully supports WhatsApp groups: mention-gated triggers (including image-only @ mentions), recent group history injection, per-group sessions, sender attribution, and a first-turn primer with group subject/member roster; heartbeats are skipped for groups.
|
- **Group chats (web provider):** Clawdis now fully supports WhatsApp groups: mention-gated triggers (including image-only @ mentions), recent group history injection, per-group sessions, sender attribution, and a first-turn primer with group subject/member roster; heartbeats are skipped for groups.
|
||||||
- **Group session primer:** The first turn of a group session now tells the agent it is in a WhatsApp group and lists known members/subject so it can address the right speaker.
|
- **Group session primer:** The first turn of a group session now tells the agent it is in a WhatsApp group and lists known members/subject so it can address the right speaker.
|
||||||
- **Media failures are surfaced:** When a web auto-reply media fetch/send fails (e.g., HTTP 404), we now append a warning to the fallback text so you know the attachment was skipped.
|
- **Media failures are surfaced:** When a web auto-reply media fetch/send fails (e.g., HTTP 404), we now append a warning to the fallback text so you know the attachment was skipped.
|
||||||
- **Verbose directives + session hints:** `/v|/verbose on|full|off` mirrors thinking: inline > session > config default. Directive-only replies with an acknowledgement; invalid levels return a hint. When enabled, tool results from JSON-emitting agents (Pi/Tau, etc.) are forwarded as metadata-only `[🛠️ <tool-name> <arg>]` messages (now streamed as they happen), and new sessions surface a `🧭 New session: <id>` hint.
|
- **Verbose directives + session hints:** `/v|/verbose on|full|off` mirrors thinking: inline > session > config default. Directive-only replies with an acknowledgement; invalid levels return a hint. When enabled, tool results from JSON-emitting agents (Pi/Tau, etc.) are forwarded as metadata-only `[🛠️ <tool-name> <arg>]` messages (now streamed as they happen), and new sessions surface a `🧭 New session: <id>` hint.
|
||||||
@@ -53,7 +53,7 @@
|
|||||||
- Verbose tool messages now include emoji + args + a short result preview for bash/read/edit/write/attach (derived from RPC tool start/end events).
|
- Verbose tool messages now include emoji + args + a short result preview for bash/read/edit/write/attach (derived from RPC tool start/end events).
|
||||||
|
|
||||||
### Security / Hardening
|
### Security / Hardening
|
||||||
- IPC socket hardened (0700 dir / 0600 socket, no symlinks/foreign owners); `warelay logout` also prunes session store.
|
- IPC socket hardened (0700 dir / 0600 socket, no symlinks/foreign owners); `clawdis logout` also prunes session store.
|
||||||
- Media server blocks symlinks and enforces path containment; logging rotates daily and prunes >24h.
|
- Media server blocks symlinks and enforces path containment; logging rotates daily and prunes >24h.
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
@@ -81,11 +81,11 @@
|
|||||||
- Heartbeat alerts now honor `responsePrefix`.
|
- Heartbeat alerts now honor `responsePrefix`.
|
||||||
- Command failures return user-friendly messages.
|
- Command failures return user-friendly messages.
|
||||||
- Test session isolation to avoid touching real `sessions.json`.
|
- Test session isolation to avoid touching real `sessions.json`.
|
||||||
- IPC reuse for `warelay send/heartbeat` prevents Signal/WhatsApp session corruption.
|
- IPC reuse for `clawdis send/heartbeat` prevents Signal/WhatsApp session corruption.
|
||||||
- Web send respects media kind (image/audio/video/document) with correct limits.
|
- Web send respects media kind (image/audio/video/document) with correct limits.
|
||||||
|
|
||||||
### Changes
|
### Changes
|
||||||
- IPC relay socket at `~/.warelay/relay.sock` with automatic CLI fallback.
|
- IPC relay socket at `~/.clawdis/relay.sock` with automatic CLI fallback.
|
||||||
- Batched inbound messages with timestamps; typing indicator after IPC sends.
|
- Batched inbound messages with timestamps; typing indicator after IPC sends.
|
||||||
- Watchdog restarts WhatsApp after long inactivity; heartbeat logging includes minutes since last message.
|
- Watchdog restarts WhatsApp after long inactivity; heartbeat logging includes minutes since last message.
|
||||||
- Early `allowFrom` filtering before decryption.
|
- Early `allowFrom` filtering before decryption.
|
||||||
@@ -94,7 +94,7 @@
|
|||||||
## 1.2.2 — 2025-11-28
|
## 1.2.2 — 2025-11-28
|
||||||
|
|
||||||
### Changes
|
### Changes
|
||||||
- Manual heartbeat sends: `warelay heartbeat --message/--body` (web provider only); `--dry-run` previews payloads.
|
- Manual heartbeat sends: `clawdis heartbeat --message/--body` (web provider only); `--dry-run` previews payloads.
|
||||||
|
|
||||||
## 1.2.1 — 2025-11-28
|
## 1.2.1 — 2025-11-28
|
||||||
|
|
||||||
|
|||||||
@@ -195,7 +195,7 @@ final class RelayProcessManager: ObservableObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private func resolveCommand() -> [String] {
|
private func resolveCommand() -> [String] {
|
||||||
// Keep it simple: rely on system-installed clawdis/warelay.
|
// Keep it simple: rely on a system-installed clawdis binary.
|
||||||
// Default to `clawdis relay`; users can provide an override via env if needed.
|
// Default to `clawdis relay`; users can provide an override via env if needed.
|
||||||
if let override = ProcessInfo.processInfo.environment["CLAWDIS_RELAY_CMD"],
|
if let override = ProcessInfo.processInfo.environment["CLAWDIS_RELAY_CMD"],
|
||||||
!override.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty
|
!override.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty
|
||||||
@@ -211,9 +211,9 @@ final class RelayProcessManager: ObservableObject {
|
|||||||
return [pnpm, "clawdis", "relay"]
|
return [pnpm, "clawdis", "relay"]
|
||||||
}
|
}
|
||||||
if let node = self.findExecutable(named: "node") {
|
if let node = self.findExecutable(named: "node") {
|
||||||
let warelay = self.defaultProjectRoot().appendingPathComponent("bin/warelay.js").path
|
let clawdis = self.defaultProjectRoot().appendingPathComponent("bin/clawdis.js").path
|
||||||
if FileManager.default.isReadableFile(atPath: warelay) {
|
if FileManager.default.isReadableFile(atPath: clawdis) {
|
||||||
return [node, warelay, "relay"]
|
return [node, clawdis, "relay"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ["clawdis", "relay"]
|
return ["clawdis", "relay"]
|
||||||
|
|||||||
@@ -155,10 +155,6 @@ enum SessionLoader {
|
|||||||
private static let legacyStorePaths: [String] = [
|
private static let legacyStorePaths: [String] = [
|
||||||
standardize(FileManager.default.homeDirectoryForCurrentUser.appendingPathComponent(".clawdis/sessions.json")
|
standardize(FileManager.default.homeDirectoryForCurrentUser.appendingPathComponent(".clawdis/sessions.json")
|
||||||
.path),
|
.path),
|
||||||
standardize(FileManager.default.homeDirectoryForCurrentUser
|
|
||||||
.appendingPathComponent(".warelay/sessions/sessions.json").path),
|
|
||||||
standardize(FileManager.default.homeDirectoryForCurrentUser.appendingPathComponent(".warelay/sessions.json")
|
|
||||||
.path),
|
|
||||||
]
|
]
|
||||||
|
|
||||||
static func configHints() -> SessionConfigHints {
|
static func configHints() -> SessionConfigHints {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ Use `pnpm` (Node 22+) from the repo root. Keep the working tree clean before tag
|
|||||||
1) **Version & metadata**
|
1) **Version & metadata**
|
||||||
- [ ] Bump `package.json` version (e.g., `1.1.0`).
|
- [ ] Bump `package.json` version (e.g., `1.1.0`).
|
||||||
- [ ] Update CLI/version strings: `src/cli/program.ts` and the Baileys user agent in `src/provider-web.ts`.
|
- [ ] Update CLI/version strings: `src/cli/program.ts` and the Baileys user agent in `src/provider-web.ts`.
|
||||||
- [ ] Confirm package metadata (name, description, repository, keywords, license) and `bin` map points to `dist/index.js` for `warelay`/`warely`/`wa`.
|
- [ ] Confirm package metadata (name, description, repository, keywords, license) and `bin` map points to `dist/index.js` for `clawdis`.
|
||||||
- [ ] If dependencies changed, run `pnpm install` so `pnpm-lock.yaml` is current.
|
- [ ] If dependencies changed, run `pnpm install` so `pnpm-lock.yaml` is current.
|
||||||
|
|
||||||
2) **Build & artifacts**
|
2) **Build & artifacts**
|
||||||
@@ -26,10 +26,10 @@ Use `pnpm` (Node 22+) from the repo root. Keep the working tree clean before tag
|
|||||||
- [ ] Confirm git status is clean; commit and push as needed.
|
- [ ] Confirm git status is clean; commit and push as needed.
|
||||||
- [ ] `npm login` (verify 2FA) if needed.
|
- [ ] `npm login` (verify 2FA) if needed.
|
||||||
- [ ] `npm publish --access public` (use `--tag beta` for pre-releases).
|
- [ ] `npm publish --access public` (use `--tag beta` for pre-releases).
|
||||||
- [ ] Verify the registry: `npm view warelay version` and `npx -y warelay@X.Y.Z --version` (or `--help`).
|
- [ ] Verify the registry: `npm view clawdis version` and `npx -y clawdis@X.Y.Z --version` (or `--help`).
|
||||||
|
|
||||||
6) **Post-publish**
|
6) **Post-publish**
|
||||||
- [ ] Tag and push: `git tag vX.Y.Z && git push origin vX.Y.Z` (or `git push --tags`).
|
- [ ] Tag and push: `git tag vX.Y.Z && git push origin vX.Y.Z` (or `git push --tags`).
|
||||||
- [ ] Create/refresh the GitHub release for `vX.Y.Z` with **title `warelay X.Y.Z`** (not just the tag); body should inline the product-facing bullets from the changelog (no bare links) **and must not repeat the title inside the body**; attach the `npm pack` tarball + checksums if you generated them.
|
- [ ] Create/refresh the GitHub release for `vX.Y.Z` with **title `clawdis X.Y.Z`** (not just the tag); body should inline the product-facing bullets from the changelog (no bare links) **and must not repeat the title inside the body**; attach the `npm pack` tarball + checksums if you generated them.
|
||||||
- [ ] From a clean temp directory (no `package.json`), run `npx -y warelay@X.Y.Z send --help` to confirm install/CLI entrypoints work.
|
- [ ] From a clean temp directory (no `package.json`), run `npx -y clawdis@X.Y.Z send --help` to confirm install/CLI entrypoints work.
|
||||||
- [ ] Announce/share release notes.
|
- [ ] Announce/share release notes.
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
# Plan: `warelay agent` (direct-to-agent invocation)
|
# Plan: `clawdis agent` (direct-to-agent invocation)
|
||||||
|
|
||||||
Goal: Add a CLI subcommand that talks directly to the configured agent/command runner (no WhatsApp send), while reusing the same session handling and config warelay already uses for auto-replies.
|
Goal: Add a CLI subcommand that talks directly to the configured agent/command runner (no WhatsApp send), while reusing the same session handling and config clawdis already uses for auto-replies.
|
||||||
|
|
||||||
## Why
|
## Why
|
||||||
- Sometimes we want to poke the agent directly (same prompt templates/sessions) without sending a WhatsApp message.
|
- Sometimes we want to poke the agent directly (same prompt templates/sessions) without sending a WhatsApp message.
|
||||||
- Current flows (`send`, relay, directives) always route through WhatsApp or add wrapping text; we need a clean “talk to agent now” tool.
|
- Current flows (`send`, relay, directives) always route through WhatsApp or add wrapping text; we need a clean “talk to agent now” tool.
|
||||||
|
|
||||||
## Behavior
|
## Behavior
|
||||||
- Command: `warelay agent`
|
- Command: `clawdis agent`
|
||||||
- Required: `--message <text>`
|
- Required: `--message <text>`
|
||||||
- Session selection:
|
- Session selection:
|
||||||
- If `--session-id` given, use it.
|
- If `--session-id` given, use it.
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# Building Your Own AI Personal Assistant with warelay
|
# Building Your Own AI Personal Assistant with clawdis
|
||||||
|
|
||||||
> **TL;DR:** CLAWDIS (Pi/Tau only) lets you run a proactive assistant over WhatsApp. It can check in on you, remember context across conversations, run commands on your Mac, and even wake you up with music. This doc was originally written for Claude Code; where you see `claude ...`, use `pi --mode rpc ...` instead. A Pi-specific rewrite is coming soon.
|
> **TL;DR:** CLAWDIS (Pi/Tau only) lets you run a proactive assistant over WhatsApp. It can check in on you, remember context across conversations, run commands on your Mac, and even wake you up with music. This doc was originally written for Claude Code; where you see `claude ...`, use `pi --mode rpc ...` instead. A Pi-specific rewrite is coming soon.
|
||||||
|
|
||||||
@@ -33,11 +33,11 @@ This is experimental software running experimental AI. The author uses it daily,
|
|||||||
|
|
||||||
### Why a Dedicated Number?
|
### Why a Dedicated Number?
|
||||||
|
|
||||||
warelay uses WhatsApp Web to receive messages. If you link your personal WhatsApp, *you* become the assistant - every message to you goes to Claude. Instead, give Claude its own identity:
|
clawdis uses WhatsApp Web to receive messages. If you link your personal WhatsApp, *you* become the assistant - every message to you goes to Claude. Instead, give Claude its own identity:
|
||||||
|
|
||||||
- 📱 **Get a second SIM** - cheap prepaid SIM, eSIM, or old phone with a number
|
- 📱 **Get a second SIM** - cheap prepaid SIM, eSIM, or old phone with a number
|
||||||
- 💬 **Install WhatsApp** on that phone and verify the number
|
- 💬 **Install WhatsApp** on that phone and verify the number
|
||||||
- 🔗 **Link to warelay** - run `warelay login` and scan the QR with that phone's WhatsApp
|
- 🔗 **Link to clawdis** - run `clawdis login` and scan the QR with that phone's WhatsApp
|
||||||
- ✉️ **Message your AI** - now you (and others) can text that number to reach Claude
|
- ✉️ **Message your AI** - now you (and others) can text that number to reach Claude
|
||||||
|
|
||||||
### The Setup
|
### The Setup
|
||||||
@@ -52,7 +52,7 @@ Your Phone (personal) Second Phone (AI)
|
|||||||
▼
|
▼
|
||||||
┌─────────────────┐
|
┌─────────────────┐
|
||||||
│ Your Mac │
|
│ Your Mac │
|
||||||
│ (warelay) │
|
│ (clawdis) │
|
||||||
│ Claude Code │
|
│ Claude Code │
|
||||||
└─────────────────┘
|
└─────────────────┘
|
||||||
```
|
```
|
||||||
@@ -65,7 +65,7 @@ The second phone just needs to stay on and connected to the internet occasionall
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
Clawd is @steipete's personal AI assistant built on warelay. Here's what makes it special:
|
Clawd is @steipete's personal AI assistant built on clawdis. Here's what makes it special:
|
||||||
|
|
||||||
- **Always available** via WhatsApp - no app switching, works on any device
|
- **Always available** via WhatsApp - no app switching, works on any device
|
||||||
- **Proactive heartbeats** - Clawd checks in every 10 minutes and can alert you to things (low battery, calendar reminders, anything it notices)
|
- **Proactive heartbeats** - Clawd checks in every 10 minutes and can alert you to things (low battery, calendar reminders, anything it notices)
|
||||||
@@ -73,11 +73,11 @@ Clawd is @steipete's personal AI assistant built on warelay. Here's what makes i
|
|||||||
- **Full Mac access** - can run commands, take screenshots, control Spotify, read/write files
|
- **Full Mac access** - can run commands, take screenshots, control Spotify, read/write files
|
||||||
- **Personal workspace** - has its own folder (`~/clawd`) where it stores notes, memories, and artifacts
|
- **Personal workspace** - has its own folder (`~/clawd`) where it stores notes, memories, and artifacts
|
||||||
|
|
||||||
The magic is in the combination: WhatsApp's ubiquity + Claude's intelligence + warelay's plumbing + your Mac's capabilities.
|
The magic is in the combination: WhatsApp's ubiquity + Claude's intelligence + clawdis's plumbing + your Mac's capabilities.
|
||||||
|
|
||||||
## Prerequisites
|
## Prerequisites
|
||||||
|
|
||||||
- Node 22+, `warelay` installed: `npm install -g warelay`
|
- Node 22+, `clawdis` installed: `npm install -g clawdis`
|
||||||
- Claude CLI installed and logged in:
|
- Claude CLI installed and logged in:
|
||||||
```sh
|
```sh
|
||||||
brew install anthropic-ai/cli/claude
|
brew install anthropic-ai/cli/claude
|
||||||
@@ -91,7 +91,7 @@ This is the actual config running on @steipete's Mac (`~/.clawdis/clawdis.json`)
|
|||||||
|
|
||||||
```json5
|
```json5
|
||||||
{
|
{
|
||||||
logging: { level: "trace", file: "/tmp/warelay/warelay.log" },
|
logging: { level: "trace", file: "/tmp/clawdis/clawdis.log" },
|
||||||
inbound: {
|
inbound: {
|
||||||
allowFrom: ["+1234567890"], // your phone number
|
allowFrom: ["+1234567890"], // your phone number
|
||||||
reply: {
|
reply: {
|
||||||
@@ -153,7 +153,7 @@ Peter trusts you with a lot of power. Don't betray that trust.`,
|
|||||||
|
|
||||||
## Heartbeats: Your Proactive Assistant
|
## Heartbeats: Your Proactive Assistant
|
||||||
|
|
||||||
This is where warelay gets interesting. Every 10 minutes (configurable), warelay pings Claude with:
|
This is where clawdis gets interesting. Every 10 minutes (configurable), clawdis pings Claude with:
|
||||||
|
|
||||||
```
|
```
|
||||||
HEARTBEAT /think:high
|
HEARTBEAT /think:high
|
||||||
@@ -197,23 +197,23 @@ Set to `0` to disable heartbeats entirely.
|
|||||||
|
|
||||||
Test it anytime:
|
Test it anytime:
|
||||||
```sh
|
```sh
|
||||||
warelay heartbeat --provider web --to +1234567890 --verbose
|
clawdis heartbeat --provider web --to +1234567890 --verbose
|
||||||
```
|
```
|
||||||
|
|
||||||
## How Messages Flow
|
## How Messages Flow
|
||||||
|
|
||||||
```
|
```
|
||||||
┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
|
┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
|
||||||
│ WhatsApp │────▶│ warelay │────▶│ Claude │────▶│ Your Mac │
|
│ WhatsApp │────▶│ clawdis │────▶│ Claude │────▶│ Your Mac │
|
||||||
│ (phone) │◀────│ relay │◀────│ CLI │◀────│ (commands) │
|
│ (phone) │◀────│ relay │◀────│ CLI │◀────│ (commands) │
|
||||||
└─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘
|
└─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘
|
||||||
```
|
```
|
||||||
|
|
||||||
1. **Inbound**: WhatsApp message arrives via Baileys (WhatsApp Web protocol)
|
1. **Inbound**: WhatsApp message arrives via Baileys (WhatsApp Web protocol)
|
||||||
2. **Queue**: warelay queues it (one Claude run at a time)
|
2. **Queue**: clawdis queues it (one Claude run at a time)
|
||||||
3. **Typing**: "composing" indicator shows while Claude thinks
|
3. **Typing**: "composing" indicator shows while Claude thinks
|
||||||
4. **Execute**: Claude runs with full shell access in your `cwd`
|
4. **Execute**: Claude runs with full shell access in your `cwd`
|
||||||
5. **Parse**: warelay extracts text + any `MEDIA:` paths from output
|
5. **Parse**: clawdis extracts text + any `MEDIA:` paths from output
|
||||||
6. **Reply**: Response sent back to WhatsApp
|
6. **Reply**: Response sent back to WhatsApp
|
||||||
|
|
||||||
## Media: Images, Voice, Documents
|
## Media: Images, Voice, Documents
|
||||||
@@ -232,19 +232,19 @@ Inbound images/audio/video are downloaded and available as `{{MediaPath}}`. Voic
|
|||||||
```
|
```
|
||||||
|
|
||||||
### Sending Media
|
### Sending Media
|
||||||
Include `MEDIA:/path/to/file.png` in Claude's output to attach images. warelay handles resizing and format conversion automatically.
|
Include `MEDIA:/path/to/file.png` in Claude's output to attach images. clawdis handles resizing and format conversion automatically.
|
||||||
|
|
||||||
## Starting the Relay
|
## Starting the Relay
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
# Foreground (see all logs)
|
# Foreground (see all logs)
|
||||||
warelay relay --provider web --verbose
|
clawdis relay --provider web --verbose
|
||||||
|
|
||||||
# Background in tmux (recommended)
|
# Background in tmux (recommended)
|
||||||
warelay relay:tmux
|
clawdis relay:tmux
|
||||||
|
|
||||||
# With immediate heartbeat on startup
|
# With immediate heartbeat on startup
|
||||||
warelay relay:heartbeat:tmux
|
clawdis relay:heartbeat:tmux
|
||||||
```
|
```
|
||||||
|
|
||||||
## Tips for a Great Personal Assistant
|
## Tips for a Great Personal Assistant
|
||||||
@@ -402,7 +402,7 @@ mcporter handles OAuth flows for services like Linear and Notion, and keeps your
|
|||||||
3. **GitHub + Linear** = AI manages your dev workflow end-to-end
|
3. **GitHub + Linear** = AI manages your dev workflow end-to-end
|
||||||
4. **Chrome DevTools** = AI can see and interact with web pages
|
4. **Chrome DevTools** = AI can see and interact with web pages
|
||||||
|
|
||||||
The combination of warelay (WhatsApp) + MCPs (services) + Claude Code (execution) creates a surprisingly capable personal assistant.
|
The combination of clawdis (WhatsApp) + MCPs (services) + Claude Code (execution) creates a surprisingly capable personal assistant.
|
||||||
|
|
||||||
### browser-tools for Web Scraping
|
### browser-tools for Web Scraping
|
||||||
|
|
||||||
@@ -475,7 +475,7 @@ Returns song title, artist, album, and Spotify link. Works great for identifying
|
|||||||
|
|
||||||
## See It In Action
|
## See It In Action
|
||||||
|
|
||||||
Check out these tweets showing warelay + Clawd in the wild:
|
Check out these tweets showing clawdis + Clawd in the wild:
|
||||||
|
|
||||||
- [Clawd with full system access via WhatsApp](https://x.com/steipete/status/1993342394184745270) - "I'll be nice to Clawd"
|
- [Clawd with full system access via WhatsApp](https://x.com/steipete/status/1993342394184745270) - "I'll be nice to Clawd"
|
||||||
- [Voice support - talk with Clawd on the go](https://x.com/steipete/status/1993455673229840588) - and it talks back!
|
- [Voice support - talk with Clawd on the go](https://x.com/steipete/status/1993455673229840588) - and it talks back!
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ Author: steipete · Status: draft spec · Date: 2025-12-05
|
|||||||
|
|
||||||
## Purpose
|
## Purpose
|
||||||
- Single macOS menu-bar app named **Clawdis** that:
|
- Single macOS menu-bar app named **Clawdis** that:
|
||||||
- Shows native notifications for Clawdis/warelay events.
|
- Shows native notifications for Clawdis/clawdis events.
|
||||||
- Owns TCC prompts (Notifications, Accessibility, Screen Recording, Automation/AppleScript, Microphone, Speech Recognition).
|
- Owns TCC prompts (Notifications, Accessibility, Screen Recording, Automation/AppleScript, Microphone, Speech Recognition).
|
||||||
- Brokers privileged actions (screen capture, shell with elevated UI context) via XPC.
|
- Brokers privileged actions (screen capture, shell with elevated UI context) via XPC.
|
||||||
- Provides a tiny CLI (`clawdis-mac`) that talks to the app; Node/TS shells out to it.
|
- Provides a tiny CLI (`clawdis-mac`) that talks to the app; Node/TS shells out to it.
|
||||||
@@ -65,7 +65,7 @@ struct Response { ok: Bool; message?: String; payload?: Data }
|
|||||||
- `status`
|
- `status`
|
||||||
- Internals: builds Request, connects via AsyncXPCConnection, prints Response as JSON to stdout.
|
- Internals: builds Request, connects via AsyncXPCConnection, prints Response as JSON to stdout.
|
||||||
|
|
||||||
## Integration with warelay/Clawdis (Node/TS)
|
## Integration with clawdis/Clawdis (Node/TS)
|
||||||
- Add helper module that shells to `clawdis-mac`:
|
- Add helper module that shells to `clawdis-mac`:
|
||||||
- Prefer `ensure-permissions` before actions that need TCC.
|
- Prefer `ensure-permissions` before actions that need TCC.
|
||||||
- Use `notify` for desktop toasts; fall back to JS notifier only if CLI missing or platform ≠ macOS.
|
- Use `notify` for desktop toasts; fall back to JS notifier only if CLI missing or platform ≠ macOS.
|
||||||
|
|||||||
@@ -149,15 +149,15 @@ export CLAWDIS_CONFIG_PATH=~/.clawdis/clawdis.json
|
|||||||
|
|
||||||
## Migrating from Warelay
|
## Migrating from Warelay
|
||||||
|
|
||||||
If you're upgrading from the old `warelay` name:
|
If you're upgrading from the old `clawdis` name:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Move config
|
# Move config
|
||||||
mv ~/.warelay ~/.clawdis
|
mv ~/.clawdis ~/.clawdis
|
||||||
mv ~/.clawdis/warelay.json ~/.clawdis/clawdis.json
|
mv ~/.clawdis/clawdis.json ~/.clawdis/clawdis.json
|
||||||
|
|
||||||
# Update any hardcoded paths in your config
|
# Update any hardcoded paths in your config
|
||||||
sed -i '' 's/warelay/clawdis/g' ~/.clawdis/clawdis.json
|
sed -i '' 's/clawdis/clawdis/g' ~/.clawdis/clawdis.json
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -37,9 +37,9 @@ Goal: add a simple heartbeat poll for command-based auto-replies (Pi/Tau) that o
|
|||||||
## Documentation
|
## Documentation
|
||||||
- Add a short README snippet under configuration showing `heartbeatMinutes` and the sentinel rule.
|
- Add a short README snippet under configuration showing `heartbeatMinutes` and the sentinel rule.
|
||||||
- Expose CLI triggers:
|
- Expose CLI triggers:
|
||||||
- `warelay heartbeat` (web provider, defaults to first `allowFrom`; optional `--to` override)
|
- `clawdis heartbeat` (web provider, defaults to first `allowFrom`; optional `--to` override)
|
||||||
- `--session-id <uuid>` forces resuming a specific session for that heartbeat
|
- `--session-id <uuid>` forces resuming a specific session for that heartbeat
|
||||||
- `warelay relay:heartbeat` to run the relay loop with an immediate heartbeat (no tmux)
|
- `clawdis relay:heartbeat` to run the relay loop with an immediate heartbeat (no tmux)
|
||||||
- `warelay relay:heartbeat:tmux` to run the same in tmux (detached, attachable)
|
- `clawdis relay:heartbeat:tmux` to run the same in tmux (detached, attachable)
|
||||||
- Relay supports `--heartbeat-now` to fire once at startup (including the tmux helper).
|
- Relay supports `--heartbeat-now` to fire once at startup (including the tmux helper).
|
||||||
- When multiple sessions are active or `allowFrom` is only `"*"`, require `--to <E.164>` or `--all` for manual heartbeats to avoid ambiguous targets.
|
- When multiple sessions are active or `allowFrom` is only `"*"`, require `--to <E.164>` or `--all` for manual heartbeats to avoid ambiguous targets.
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ clawdis status
|
|||||||
|
|
||||||
- [Configuration Guide](./configuration.md) — Setting up your CLAWDIS
|
- [Configuration Guide](./configuration.md) — Setting up your CLAWDIS
|
||||||
- [Agent Integration](./agents.md) — Connecting AI agents
|
- [Agent Integration](./agents.md) — Connecting AI agents
|
||||||
- [Direct Agent CLI](./agent-send.md) — Use `warelay agent` without sending WhatsApp messages
|
- [Direct Agent CLI](./agent-send.md) — Use `clawdis agent` without sending WhatsApp messages
|
||||||
- [Group Chats](./groups.md) — Mention patterns and filtering
|
- [Group Chats](./groups.md) — Mention patterns and filtering
|
||||||
- [Media Handling](./media.md) — Images, voice, documents
|
- [Media Handling](./media.md) — Images, voice, documents
|
||||||
- [Session Management](./session.md) — How conversations are keyed and reset
|
- [Session Management](./session.md) — How conversations are keyed and reset
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
Date: 2025-12-06 · Status: draft · Owner: steipete
|
Date: 2025-12-06 · Status: draft · Owner: steipete
|
||||||
|
|
||||||
## Goal
|
## Goal
|
||||||
Run the Node-based Clawdis/warelay relay as a direct child of the LSUIElement app (instead of a launchd agent) while keeping all TCC-sensitive work inside the Swift app/XPC and wiring the existing “Clawdis Active” toggle to start/stop the child.
|
Run the Node-based Clawdis/clawdis relay as a direct child of the LSUIElement app (instead of a launchd agent) while keeping all TCC-sensitive work inside the Swift app/XPC and wiring the existing “Clawdis Active” toggle to start/stop the child.
|
||||||
|
|
||||||
## When to prefer the child-process mode
|
## When to prefer the child-process mode
|
||||||
- You want relay lifetime strictly coupled to the menu-bar app (dies when the app quits) and controlled by the “Clawdis Active” toggle without touching launchd.
|
- You want relay lifetime strictly coupled to the menu-bar app (dies when the app quits) and controlled by the “Clawdis Active” toggle without touching launchd.
|
||||||
@@ -30,7 +30,7 @@ Run the Node-based Clawdis/warelay relay as a direct child of the LSUIElement ap
|
|||||||
- `execution: Execution?` from `Swift Subprocess` to track the child.
|
- `execution: Execution?` from `Swift Subprocess` to track the child.
|
||||||
- `start(config)` called when “Clawdis Active” flips ON:
|
- `start(config)` called when “Clawdis Active” flips ON:
|
||||||
- binary: bundled Node or packaged relay CLI under `Clawdis.app/Contents/Resources/Relay/`
|
- binary: bundled Node or packaged relay CLI under `Clawdis.app/Contents/Resources/Relay/`
|
||||||
- args: current warelay/clawdis entrypoint and flags
|
- args: current clawdis/clawdis entrypoint and flags
|
||||||
- cwd/env: point to `~/.clawdis` as today; inject `PATH` if the embedded Node isn’t on PATH
|
- cwd/env: point to `~/.clawdis` as today; inject `PATH` if the embedded Node isn’t on PATH
|
||||||
- output: stream stdout/stderr to `/tmp/clawdis-relay.log` (cap buffer via Subprocess OutputLimits)
|
- output: stream stdout/stderr to `/tmp/clawdis-relay.log` (cap buffer via Subprocess OutputLimits)
|
||||||
- restart: optional linear/backoff restart if exit was non-zero and Active is still true
|
- restart: optional linear/backoff restart if exit was non-zero and Active is still true
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
# Web Relay Troubleshooting (Nov 26, 2025)
|
# Web Relay Troubleshooting (Nov 26, 2025)
|
||||||
|
|
||||||
## Symptoms & quick fixes
|
## Symptoms & quick fixes
|
||||||
- **Stream Errored / Conflict / status 409–515:** WhatsApp closed the socket because another session is active or creds went stale. Run `warelay logout` then `warelay login --provider web` and restart the relay.
|
- **Stream Errored / Conflict / status 409–515:** WhatsApp closed the socket because another session is active or creds went stale. Run `clawdis logout` then `clawdis login --provider web` and restart the relay.
|
||||||
- **Logged out:** Console prints “session logged out”; re-link with `warelay login --provider web`.
|
- **Logged out:** Console prints “session logged out”; re-link with `clawdis login --provider web`.
|
||||||
- **Repeated retries then exit:** Reconnects are capped (default 12 attempts). Tune with `--web-retries`, `--web-retry-initial`, `--web-retry-max`, or config `web.reconnect`.
|
- **Repeated retries then exit:** Reconnects are capped (default 12 attempts). Tune with `--web-retries`, `--web-retry-initial`, `--web-retry-max`, or config `web.reconnect`.
|
||||||
- **No inbound messages:** Ensure the QR-linked account is online in WhatsApp, and check logs for `web-heartbeat` to confirm auth age/connection.
|
- **No inbound messages:** Ensure the QR-linked account is online in WhatsApp, and check logs for `web-heartbeat` to confirm auth age/connection.
|
||||||
- **Fast nuke:** From an allowed WhatsApp sender you can send `/restart` to kick `com.steipete.clawdis` via launchd; wait a few seconds for it to relink.
|
- **Fast nuke:** From an allowed WhatsApp sender you can send `/restart` to kick `com.steipete.clawdis` via launchd; wait a few seconds for it to relink.
|
||||||
|
|
||||||
## Helpful commands
|
## Helpful commands
|
||||||
- Start relay web-only: `pnpm warelay relay --provider web --verbose`
|
- Start relay web-only: `pnpm clawdis relay --provider web --verbose`
|
||||||
- Show who is linked: `pnpm warelay relay --provider web --verbose` (first line prints the linked E.164)
|
- Show who is linked: `pnpm clawdis relay --provider web --verbose` (first line prints the linked E.164)
|
||||||
- Logout (clear creds): `pnpm warelay logout`
|
- Logout (clear creds): `pnpm clawdis logout`
|
||||||
- Relink: `pnpm warelay login --provider web`
|
- Relink: `pnpm clawdis login --provider web`
|
||||||
- Tail logs (default): `tail -f /tmp/warelay/warelay.log`
|
- Tail logs (default): `tail -f /tmp/clawdis/clawdis.log`
|
||||||
|
|
||||||
## Reading the logs
|
## Reading the logs
|
||||||
- `web-reconnect`: close reasons, retry/backoff, max-attempt exit.
|
- `web-reconnect`: close reasons, retry/backoff, max-attempt exit.
|
||||||
@@ -25,7 +25,7 @@
|
|||||||
- Chatty monitors: increase `--web-heartbeat` interval if log volume is high.
|
- Chatty monitors: increase `--web-heartbeat` interval if log volume is high.
|
||||||
|
|
||||||
## If it keeps failing
|
## If it keeps failing
|
||||||
1) `warelay logout` → `warelay login --provider web` (fresh QR link).
|
1) `clawdis logout` → `clawdis login --provider web` (fresh QR link).
|
||||||
2) Ensure no other device/browser is using the same WA Web session.
|
2) Ensure no other device/browser is using the same WA Web session.
|
||||||
3) Check WhatsApp mobile app is online and not in low-power mode.
|
3) Check WhatsApp mobile app is online and not in low-power mode.
|
||||||
4) If status is 515, let the client restart once after pairing (already handled automatically).
|
4) If status is 515, let the client restart once after pairing (already handled automatically).
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
Clawdis treats **one session as primary**. By default the canonical key is `main`; set `inbound.reply.session.mainKey` to change it. Older/local sessions can stay on disk, but only the primary key is used for desktop/web chat and direct agent calls.
|
Clawdis treats **one session as primary**. By default the canonical key is `main`; set `inbound.reply.session.mainKey` to change it. Older/local sessions can stay on disk, but only the primary key is used for desktop/web chat and direct agent calls.
|
||||||
|
|
||||||
## Where state lives
|
## Where state lives
|
||||||
- Store file: `~/.clawdis/sessions/sessions.json` (legacy: `~/.warelay/sessions.json`).
|
- Store file: `~/.clawdis/sessions/sessions.json` (legacy: `~/.clawdis/sessions.json`).
|
||||||
- Transcripts: `~/.clawdis/sessions/<SessionId>.jsonl` (one file per session id).
|
- Transcripts: `~/.clawdis/sessions/<SessionId>.jsonl` (one file per session id).
|
||||||
- The store is a map `sessionKey -> { sessionId, updatedAt, ... }`. Deleting entries is safe; they are recreated on demand.
|
- The store is a map `sessionKey -> { sessionId, updatedAt, ... }`. Deleting entries is safe; they are recreated on demand.
|
||||||
|
|
||||||
|
|||||||
10
docs/tmux.md
10
docs/tmux.md
@@ -6,12 +6,12 @@
|
|||||||
- Keep the relay code itself tmux-agnostic; tmux is only a launcher concern.
|
- Keep the relay code itself tmux-agnostic; tmux is only a launcher concern.
|
||||||
|
|
||||||
## Commands
|
## Commands
|
||||||
- `warelay relay:tmux` — restarts the `warelay-relay` session running `pnpm warelay relay --verbose`, then attaches (skips attach when stdout isn’t a TTY).
|
- `clawdis relay:tmux` — restarts the `clawdis-relay` session running `pnpm clawdis relay --verbose`, then attaches (skips attach when stdout isn’t a TTY).
|
||||||
- `warelay relay:tmux:attach` — attach to the existing session without restarting it.
|
- `clawdis relay:tmux:attach` — attach to the existing session without restarting it.
|
||||||
- `warelay relay:heartbeat:tmux` — same as `relay:tmux` but adds `--heartbeat-now` so Pi is pinged immediately on startup.
|
- `clawdis relay:heartbeat:tmux` — same as `relay:tmux` but adds `--heartbeat-now` so Pi is pinged immediately on startup.
|
||||||
|
|
||||||
All helpers use the fixed session name `warelay-relay`.
|
All helpers use the fixed session name `clawdis-relay`.
|
||||||
|
|
||||||
## Logs
|
## Logs
|
||||||
- The relay always writes to the configured file logger (defaults to `/tmp/warelay/warelay.log`); on start it prints the active log path and level.
|
- The relay always writes to the configured file logger (defaults to `/tmp/clawdis/clawdis.log`); on start it prints the active log path and level.
|
||||||
- tmux is just for interactive viewing; you can also tail the log file or use another supervisor if you prefer.
|
- tmux is just for interactive viewing; you can also tail the log file or use another supervisor if you prefer.
|
||||||
|
|||||||
@@ -5,18 +5,12 @@
|
|||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"bin": {
|
"bin": {
|
||||||
"clawdis": "bin/warelay.js",
|
"clawdis": "dist/index.js"
|
||||||
"warelay": "bin/warelay.js",
|
|
||||||
"warely": "bin/warelay.js",
|
|
||||||
"wa": "bin/warelay.js"
|
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "tsx src/index.ts",
|
"dev": "tsx src/index.ts",
|
||||||
"build": "tsc -p tsconfig.json",
|
"build": "tsc -p tsconfig.json",
|
||||||
"start": "tsx src/index.ts",
|
"start": "tsx src/index.ts",
|
||||||
"warelay": "tsx src/index.ts",
|
|
||||||
"warely": "tsx src/index.ts",
|
|
||||||
"wa": "tsx src/index.ts",
|
|
||||||
"clawdis": "tsx src/index.ts",
|
"clawdis": "tsx src/index.ts",
|
||||||
"clawdis:rpc": "tsx src/index.ts agent --mode rpc --json",
|
"clawdis:rpc": "tsx src/index.ts agent --mode rpc --json",
|
||||||
"lint": "biome check src",
|
"lint": "biome check src",
|
||||||
|
|||||||
@@ -355,7 +355,7 @@ describe("runCommandReply (pi)", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("parses MEDIA tokens and respects mediaMaxMb for local files", async () => {
|
it("parses MEDIA tokens and respects mediaMaxMb for local files", async () => {
|
||||||
const tmp = path.join(os.tmpdir(), `warelay-test-${Date.now()}.bin`);
|
const tmp = path.join(os.tmpdir(), `clawdis-test-${Date.now()}.bin`);
|
||||||
const bigBuffer = Buffer.alloc(2 * 1024 * 1024, 1);
|
const bigBuffer = Buffer.alloc(2 * 1024 * 1024, 1);
|
||||||
await fs.writeFile(tmp, bigBuffer);
|
await fs.writeFile(tmp, bigBuffer);
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ describe("transcribeInboundAudio", () => {
|
|||||||
|
|
||||||
it("downloads mediaUrl to temp file and returns transcript", async () => {
|
it("downloads mediaUrl to temp file and returns transcript", async () => {
|
||||||
const tmpBuf = Buffer.from("audio-bytes");
|
const tmpBuf = Buffer.from("audio-bytes");
|
||||||
const tmpFile = path.join(os.tmpdir(), `warelay-audio-${Date.now()}.ogg`);
|
const tmpFile = path.join(os.tmpdir(), `clawdis-audio-${Date.now()}.ogg`);
|
||||||
await fs.writeFile(tmpFile, tmpBuf);
|
await fs.writeFile(tmpFile, tmpBuf);
|
||||||
|
|
||||||
const fetchMock = vi.fn(async () => ({
|
const fetchMock = vi.fn(async () => ({
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ const configSpy = vi.spyOn(configModule, "loadConfig");
|
|||||||
function makeStorePath() {
|
function makeStorePath() {
|
||||||
return path.join(
|
return path.join(
|
||||||
os.tmpdir(),
|
os.tmpdir(),
|
||||||
`warelay-agent-test-${Date.now()}-${Math.random()}.json`,
|
`clawdis-agent-test-${Date.now()}-${Math.random()}.json`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { PassThrough } from "node:stream";
|
|||||||
import { afterAll, beforeAll, describe, expect, it, vi } from "vitest";
|
import { afterAll, beforeAll, describe, expect, it, vi } from "vitest";
|
||||||
|
|
||||||
const realOs = await vi.importActual<typeof import("node:os")>("node:os");
|
const realOs = await vi.importActual<typeof import("node:os")>("node:os");
|
||||||
const HOME = path.join(realOs.tmpdir(), "warelay-home-redirect");
|
const HOME = path.join(realOs.tmpdir(), "clawdis-home-redirect");
|
||||||
const mockRequest = vi.fn();
|
const mockRequest = vi.fn();
|
||||||
|
|
||||||
vi.doMock("node:os", () => ({
|
vi.doMock("node:os", () => ({
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import sharp from "sharp";
|
|||||||
import { afterAll, beforeAll, describe, expect, it, vi } from "vitest";
|
import { afterAll, beforeAll, describe, expect, it, vi } from "vitest";
|
||||||
|
|
||||||
const realOs = await vi.importActual<typeof import("node:os")>("node:os");
|
const realOs = await vi.importActual<typeof import("node:os")>("node:os");
|
||||||
const HOME = path.join(realOs.tmpdir(), "warelay-home-test");
|
const HOME = path.join(realOs.tmpdir(), "clawdis-home-test");
|
||||||
|
|
||||||
vi.mock("node:os", () => ({
|
vi.mock("node:os", () => ({
|
||||||
default: { homedir: () => HOME, tmpdir: () => realOs.tmpdir() },
|
default: { homedir: () => HOME, tmpdir: () => realOs.tmpdir() },
|
||||||
@@ -25,7 +25,7 @@ describe("media store", () => {
|
|||||||
|
|
||||||
it("creates and returns media directory", async () => {
|
it("creates and returns media directory", async () => {
|
||||||
const dir = await store.ensureMediaDir();
|
const dir = await store.ensureMediaDir();
|
||||||
expect(dir).toContain("warelay-home-test");
|
expect(dir).toContain("clawdis-home-test");
|
||||||
const stat = await fs.stat(dir);
|
const stat = await fs.stat(dir);
|
||||||
expect(stat.isDirectory()).toBe(true);
|
expect(stat.isDirectory()).toBe(true);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ describe("withWhatsAppPrefix", () => {
|
|||||||
describe("ensureDir", () => {
|
describe("ensureDir", () => {
|
||||||
it("creates nested directory", async () => {
|
it("creates nested directory", async () => {
|
||||||
const tmp = await fs.promises.mkdtemp(
|
const tmp = await fs.promises.mkdtemp(
|
||||||
path.join(os.tmpdir(), "warelay-test-"),
|
path.join(os.tmpdir(), "clawdis-test-"),
|
||||||
);
|
);
|
||||||
const target = path.join(tmp, "nested", "dir");
|
const target = path.join(tmp, "nested", "dir");
|
||||||
await ensureDir(target);
|
await ensureDir(target);
|
||||||
|
|||||||
@@ -71,5 +71,5 @@ export function sleep(ms: number) {
|
|||||||
return new Promise((resolve) => setTimeout(resolve, ms));
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fixed configuration root; legacy ~/.warelay is no longer used.
|
// Fixed configuration root; legacy ~/.clawdis is no longer used.
|
||||||
export const CONFIG_DIR = path.join(os.homedir(), ".clawdis");
|
export const CONFIG_DIR = path.join(os.homedir(), ".clawdis");
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ import {
|
|||||||
const makeSessionStore = async (
|
const makeSessionStore = async (
|
||||||
entries: Record<string, unknown> = {},
|
entries: Record<string, unknown> = {},
|
||||||
): Promise<{ storePath: string; cleanup: () => Promise<void> }> => {
|
): Promise<{ storePath: string; cleanup: () => Promise<void> }> => {
|
||||||
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "warelay-session-"));
|
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "clawdis-session-"));
|
||||||
const storePath = path.join(dir, "sessions.json");
|
const storePath = path.join(dir, "sessions.json");
|
||||||
await fs.writeFile(storePath, JSON.stringify(entries));
|
await fs.writeFile(storePath, JSON.stringify(entries));
|
||||||
return {
|
return {
|
||||||
@@ -229,7 +229,7 @@ describe("runWebHeartbeatOnce", () => {
|
|||||||
|
|
||||||
it("does not refresh updatedAt when heartbeat is skipped", async () => {
|
it("does not refresh updatedAt when heartbeat is skipped", async () => {
|
||||||
const tmpDir = await fs.mkdtemp(
|
const tmpDir = await fs.mkdtemp(
|
||||||
path.join(os.tmpdir(), "warelay-heartbeat-"),
|
path.join(os.tmpdir(), "clawdis-heartbeat-"),
|
||||||
);
|
);
|
||||||
const storePath = path.join(tmpDir, "sessions.json");
|
const storePath = path.join(tmpDir, "sessions.json");
|
||||||
const now = Date.now();
|
const now = Date.now();
|
||||||
@@ -269,7 +269,7 @@ describe("runWebHeartbeatOnce", () => {
|
|||||||
|
|
||||||
it("heartbeat reuses existing session id when last inbound is present", async () => {
|
it("heartbeat reuses existing session id when last inbound is present", async () => {
|
||||||
const tmpDir = await fs.mkdtemp(
|
const tmpDir = await fs.mkdtemp(
|
||||||
path.join(os.tmpdir(), "warelay-heartbeat-session-"),
|
path.join(os.tmpdir(), "clawdis-heartbeat-session-"),
|
||||||
);
|
);
|
||||||
const storePath = path.join(tmpDir, "sessions.json");
|
const storePath = path.join(tmpDir, "sessions.json");
|
||||||
const sessionId = "sess-keep";
|
const sessionId = "sess-keep";
|
||||||
@@ -319,7 +319,7 @@ describe("runWebHeartbeatOnce", () => {
|
|||||||
|
|
||||||
it("heartbeat honors session-id override and seeds store", async () => {
|
it("heartbeat honors session-id override and seeds store", async () => {
|
||||||
const tmpDir = await fs.mkdtemp(
|
const tmpDir = await fs.mkdtemp(
|
||||||
path.join(os.tmpdir(), "warelay-heartbeat-override-"),
|
path.join(os.tmpdir(), "clawdis-heartbeat-override-"),
|
||||||
);
|
);
|
||||||
const storePath = path.join(tmpDir, "sessions.json");
|
const storePath = path.join(tmpDir, "sessions.json");
|
||||||
await fs.writeFile(storePath, JSON.stringify({}));
|
await fs.writeFile(storePath, JSON.stringify({}));
|
||||||
@@ -527,7 +527,7 @@ describe("web auto-reply", () => {
|
|||||||
|
|
||||||
it("skips reply heartbeat when requests are running", async () => {
|
it("skips reply heartbeat when requests are running", async () => {
|
||||||
const tmpDir = await fs.mkdtemp(
|
const tmpDir = await fs.mkdtemp(
|
||||||
path.join(os.tmpdir(), "warelay-heartbeat-queue-"),
|
path.join(os.tmpdir(), "clawdis-heartbeat-queue-"),
|
||||||
);
|
);
|
||||||
const storePath = path.join(tmpDir, "sessions.json");
|
const storePath = path.join(tmpDir, "sessions.json");
|
||||||
await fs.writeFile(storePath, JSON.stringify({}));
|
await fs.writeFile(storePath, JSON.stringify({}));
|
||||||
@@ -1126,7 +1126,7 @@ describe("web auto-reply", () => {
|
|||||||
|
|
||||||
it("emits heartbeat logs with connection metadata", async () => {
|
it("emits heartbeat logs with connection metadata", async () => {
|
||||||
vi.useFakeTimers();
|
vi.useFakeTimers();
|
||||||
const logPath = `/tmp/warelay-heartbeat-${crypto.randomUUID()}.log`;
|
const logPath = `/tmp/clawdis-heartbeat-${crypto.randomUUID()}.log`;
|
||||||
setLoggerOverride({ level: "trace", file: logPath });
|
setLoggerOverride({ level: "trace", file: logPath });
|
||||||
|
|
||||||
const runtime = {
|
const runtime = {
|
||||||
@@ -1168,7 +1168,7 @@ describe("web auto-reply", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("logs outbound replies to file", async () => {
|
it("logs outbound replies to file", async () => {
|
||||||
const logPath = `/tmp/warelay-log-test-${crypto.randomUUID()}.log`;
|
const logPath = `/tmp/clawdis-log-test-${crypto.randomUUID()}.log`;
|
||||||
setLoggerOverride({ level: "trace", file: logPath });
|
setLoggerOverride({ level: "trace", file: logPath });
|
||||||
|
|
||||||
let capturedOnMessage:
|
let capturedOnMessage:
|
||||||
@@ -1362,7 +1362,7 @@ describe("web auto-reply", () => {
|
|||||||
sendMedia: vi.fn(),
|
sendMedia: vi.fn(),
|
||||||
});
|
});
|
||||||
|
|
||||||
// HEARTBEAT_OK should NOT have prefix - warelay needs exact match
|
// HEARTBEAT_OK should NOT have prefix - clawdis needs exact match
|
||||||
expect(reply).toHaveBeenCalledWith(HEARTBEAT_TOKEN);
|
expect(reply).toHaveBeenCalledWith(HEARTBEAT_TOKEN);
|
||||||
resetLoadConfigMock();
|
resetLoadConfigMock();
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ vi.mock("../config/config.js", () => ({
|
|||||||
|
|
||||||
const HOME = path.join(
|
const HOME = path.join(
|
||||||
os.tmpdir(),
|
os.tmpdir(),
|
||||||
`warelay-inbound-media-${crypto.randomUUID()}`,
|
`clawdis-inbound-media-${crypto.randomUUID()}`,
|
||||||
);
|
);
|
||||||
process.env.HOME = HOME;
|
process.env.HOME = HOME;
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ describe("web media loading", () => {
|
|||||||
.jpeg({ quality: 95 })
|
.jpeg({ quality: 95 })
|
||||||
.toBuffer();
|
.toBuffer();
|
||||||
|
|
||||||
const file = path.join(os.tmpdir(), `warelay-media-${Date.now()}.jpg`);
|
const file = path.join(os.tmpdir(), `clawdis-media-${Date.now()}.jpg`);
|
||||||
tmpFiles.push(file);
|
tmpFiles.push(file);
|
||||||
await fs.writeFile(file, buffer);
|
await fs.writeFile(file, buffer);
|
||||||
|
|
||||||
@@ -45,7 +45,7 @@ describe("web media loading", () => {
|
|||||||
})
|
})
|
||||||
.png()
|
.png()
|
||||||
.toBuffer();
|
.toBuffer();
|
||||||
const wrongExt = path.join(os.tmpdir(), `warelay-media-${Date.now()}.bin`);
|
const wrongExt = path.join(os.tmpdir(), `clawdis-media-${Date.now()}.bin`);
|
||||||
tmpFiles.push(wrongExt);
|
tmpFiles.push(wrongExt);
|
||||||
await fs.writeFile(wrongExt, pngBuffer);
|
await fs.writeFile(wrongExt, pngBuffer);
|
||||||
|
|
||||||
|
|||||||
@@ -169,7 +169,7 @@ describe("web monitor inbox", () => {
|
|||||||
it("logs inbound bodies to file", async () => {
|
it("logs inbound bodies to file", async () => {
|
||||||
const logPath = path.join(
|
const logPath = path.join(
|
||||||
os.tmpdir(),
|
os.tmpdir(),
|
||||||
`warelay-log-test-${crypto.randomUUID()}.log`,
|
`clawdis-log-test-${crypto.randomUUID()}.log`,
|
||||||
);
|
);
|
||||||
setLoggerOverride({ level: "trace", file: logPath });
|
setLoggerOverride({ level: "trace", file: logPath });
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user