@@ -108431,7 +108486,7 @@ var init_ArtifactElement = __esmMin((() => {
}));
//#endregion
-//#region node_modules/.pnpm/katex@0.16.27/node_modules/katex/dist/katex.mjs
+//#region node_modules/katex/dist/katex.mjs
/**
* Escapes text to prevent scripting attacks.
*/
@@ -131193,14 +131248,11 @@ var init_katex = __esmMin((() => {
case "\\htmlData": {
var data = value.split(",");
for (var i$7 = 0; i$7 < data.length; i$7++) {
- var item = data[i$7];
- var firstEquals = item.indexOf("=");
- if (firstEquals < 0) {
- throw new ParseError("\\htmlData key/value '" + item + "'" + " missing equals sign");
+ var keyVal = data[i$7].split("=");
+ if (keyVal.length !== 2) {
+ throw new ParseError("Error parsing key-value for \\htmlData");
}
- var key = item.slice(0, firstEquals);
- var _value = item.slice(firstEquals + 1);
- attributes["data-" + key.trim()] = _value;
+ attributes["data-" + keyVal[0].trim()] = keyVal[1].trim();
}
trustContext = {
command: "\\htmlData",
@@ -135674,7 +135726,7 @@ var init_katex = __esmMin((() => {
return renderError(error$2, expression, settings);
}
};
- version$2 = "0.16.27";
+ version$2 = "0.16.26";
__domTree = {
Span,
Anchor,
@@ -135701,7 +135753,7 @@ var init_katex = __esmMin((() => {
}));
//#endregion
-//#region node_modules/.pnpm/@mariozechner+mini-lit@0.2.1_lit@3.3.1_tailwindcss@4.1.17/node_modules/@mariozechner/mini-lit/node_modules/marked/lib/marked.esm.js
+//#region node_modules/@mariozechner/mini-lit/node_modules/marked/lib/marked.esm.js
/**
* marked v16.4.2 - a markdown parser
* Copyright (c) 2018-2025, MarkedJS. (MIT License)
@@ -137193,7 +137245,7 @@ Please report this to https://github.com/markedjs/marked.`, e$10) {
}));
//#endregion
-//#region node_modules/.pnpm/@mariozechner+mini-lit@0.2.1_lit@3.3.1_tailwindcss@4.1.17/node_modules/@mariozechner/mini-lit/dist/MarkdownBlock.js
+//#region node_modules/@mariozechner/mini-lit/dist/MarkdownBlock.js
var __decorate$16, MarkdownBlock;
var init_MarkdownBlock = __esmMin((() => {
init_katex();
@@ -137398,7 +137450,7 @@ var init_MarkdownBlock = __esmMin((() => {
}));
//#endregion
-//#region node_modules/.pnpm/@mariozechner+mini-lit@0.2.1_lit@3.3.1_tailwindcss@4.1.17/node_modules/@mariozechner/mini-lit/dist/DownloadButton.js
+//#region node_modules/@mariozechner/mini-lit/dist/DownloadButton.js
function DownloadButton({ content, filename, mimeType = "text/plain", title = i18n("Download"), showText = false, size = "sm", variant = "ghost", iconSize = "sm", isBase64 = false }) {
const handleDownload = () => {
let blobContent;
@@ -186554,7 +186606,7 @@ var init_es = __esmMin((() => {
}));
//#endregion
-//#region node_modules/.pnpm/@mariozechner+mini-lit@0.2.1_lit@3.3.1_tailwindcss@4.1.17/node_modules/@mariozechner/mini-lit/dist/CopyButton.js
+//#region node_modules/@mariozechner/mini-lit/dist/CopyButton.js
var __decorate$12, CopyButton;
var init_CopyButton = __esmMin((() => {
init_lit();
@@ -186699,7 +186751,7 @@ var init_Console = __esmMin((() => {
}));
//#endregion
-//#region node_modules/.pnpm/@mariozechner+mini-lit@0.2.1_lit@3.3.1_tailwindcss@4.1.17/node_modules/@mariozechner/mini-lit/dist/PreviewCodeToggle.js
+//#region node_modules/@mariozechner/mini-lit/dist/PreviewCodeToggle.js
var __decorate$10, PreviewCodeToggle;
var init_PreviewCodeToggle = __esmMin((() => {
init_lit();
@@ -188035,7 +188087,7 @@ var init_artifacts$1 = __esmMin((() => {
}));
//#endregion
-//#region node_modules/.pnpm/highlight.js@11.11.1/node_modules/highlight.js/lib/core.js
+//#region node_modules/highlight.js/lib/core.js
var require_core = /* @__PURE__ */ __commonJSMin(((exports, module) => {
function deepFreeze(obj) {
if (obj instanceof Map) {
@@ -190042,7 +190094,7 @@ var require_core = /* @__PURE__ */ __commonJSMin(((exports, module) => {
}));
//#endregion
-//#region node_modules/.pnpm/highlight.js@11.11.1/node_modules/highlight.js/es/core.js
+//#region node_modules/highlight.js/es/core.js
var import_core, core_default;
var init_core = __esmMin((() => {
import_core = /* @__PURE__ */ __toESM(require_core(), 1);
@@ -190050,7 +190102,7 @@ var init_core = __esmMin((() => {
}));
//#endregion
-//#region node_modules/.pnpm/highlight.js@11.11.1/node_modules/highlight.js/es/languages/bash.js
+//#region node_modules/highlight.js/es/languages/bash.js
/** @type LanguageFn */
function bash(hljs$1) {
const regex = hljs$1.regex;
@@ -190410,7 +190462,7 @@ function bash(hljs$1) {
var init_bash = __esmMin((() => {}));
//#endregion
-//#region node_modules/.pnpm/highlight.js@11.11.1/node_modules/highlight.js/es/languages/css.js
+//#region node_modules/highlight.js/es/languages/css.js
/** @type LanguageFn */
function css(hljs$1) {
const regex = hljs$1.regex;
@@ -191298,7 +191350,7 @@ var init_css$1 = __esmMin((() => {
}));
//#endregion
-//#region node_modules/.pnpm/highlight.js@11.11.1/node_modules/highlight.js/es/languages/javascript.js
+//#region node_modules/highlight.js/es/languages/javascript.js
/** @type LanguageFn */
function javascript(hljs$1) {
const regex = hljs$1.regex;
@@ -191870,7 +191922,7 @@ var init_javascript = __esmMin((() => {
}));
//#endregion
-//#region node_modules/.pnpm/highlight.js@11.11.1/node_modules/highlight.js/es/languages/json.js
+//#region node_modules/highlight.js/es/languages/json.js
function json(hljs$1) {
const ATTRIBUTE = {
className: "attr",
@@ -191910,7 +191962,7 @@ function json(hljs$1) {
var init_json$1 = __esmMin((() => {}));
//#endregion
-//#region node_modules/.pnpm/highlight.js@11.11.1/node_modules/highlight.js/es/languages/python.js
+//#region node_modules/highlight.js/es/languages/python.js
function python(hljs$1) {
const regex = hljs$1.regex;
const IDENT_RE$6 = /[\p{XID_Start}_]\p{XID_Continue}*/u;
@@ -192271,7 +192323,7 @@ function python(hljs$1) {
var init_python = __esmMin((() => {}));
//#endregion
-//#region node_modules/.pnpm/highlight.js@11.11.1/node_modules/highlight.js/es/languages/sql.js
+//#region node_modules/highlight.js/es/languages/sql.js
function sql(hljs$1) {
const regex = hljs$1.regex;
const COMMENT_MODE = hljs$1.COMMENT("--", "$");
@@ -192900,7 +192952,7 @@ function sql(hljs$1) {
var init_sql = __esmMin((() => {}));
//#endregion
-//#region node_modules/.pnpm/highlight.js@11.11.1/node_modules/highlight.js/es/languages/typescript.js
+//#region node_modules/highlight.js/es/languages/typescript.js
/** @type LanguageFn */
function javascript$1(hljs$1) {
const regex = hljs$1.regex;
@@ -193577,7 +193629,7 @@ var init_typescript = __esmMin((() => {
}));
//#endregion
-//#region node_modules/.pnpm/highlight.js@11.11.1/node_modules/highlight.js/es/languages/xml.js
+//#region node_modules/highlight.js/es/languages/xml.js
/** @type LanguageFn */
function xml(hljs$1) {
const regex = hljs$1.regex;
@@ -193753,7 +193805,7 @@ function xml(hljs$1) {
var init_xml$1 = __esmMin((() => {}));
//#endregion
-//#region node_modules/.pnpm/@mariozechner+mini-lit@0.2.1_lit@3.3.1_tailwindcss@4.1.17/node_modules/@mariozechner/mini-lit/dist/CodeBlock.js
+//#region node_modules/@mariozechner/mini-lit/dist/CodeBlock.js
var __decorate$2, CodeBlock;
var init_CodeBlock = __esmMin((() => {
init_core();
@@ -193912,7 +193964,7 @@ ${this.content || ""} {
Diff$1 = class {
@@ -194139,7 +194191,7 @@ var init_base = __esmMin((() => {
}));
//#endregion
-//#region node_modules/.pnpm/diff@8.0.2/node_modules/diff/libesm/diff/character.js
+//#region node_modules/diff/libesm/diff/character.js
function diffChars(oldStr, newStr, options) {
return characterDiff.diff(oldStr, newStr, options);
}
@@ -194151,7 +194203,7 @@ var init_character = __esmMin((() => {
}));
//#endregion
-//#region node_modules/.pnpm/diff@8.0.2/node_modules/diff/libesm/util/string.js
+//#region node_modules/diff/libesm/util/string.js
function longestCommonPrefix(str1, str2) {
let i$7;
for (i$7 = 0; i$7 < str1.length && i$7 < str2.length; i$7++) {
@@ -194261,7 +194313,7 @@ function leadingWs(string) {
var init_string = __esmMin((() => {}));
//#endregion
-//#region node_modules/.pnpm/diff@8.0.2/node_modules/diff/libesm/diff/word.js
+//#region node_modules/diff/libesm/diff/word.js
function diffWords(oldStr, newStr, options) {
if ((options === null || options === void 0 ? void 0 : options.ignoreWhitespace) != null && !options.ignoreWhitespace) {
return diffWordsWithSpace(oldStr, newStr, options);
@@ -194412,7 +194464,7 @@ var init_word = __esmMin((() => {
}));
//#endregion
-//#region node_modules/.pnpm/diff@8.0.2/node_modules/diff/libesm/util/params.js
+//#region node_modules/diff/libesm/util/params.js
function generateOptions(options, defaults) {
if (typeof options === "function") {
defaults.callback = options;
@@ -194429,7 +194481,7 @@ function generateOptions(options, defaults) {
var init_params = __esmMin((() => {}));
//#endregion
-//#region node_modules/.pnpm/diff@8.0.2/node_modules/diff/libesm/diff/line.js
+//#region node_modules/diff/libesm/diff/line.js
function diffLines(oldStr, newStr, options) {
return lineDiff.diff(oldStr, newStr, options);
}
@@ -194487,7 +194539,7 @@ var init_line = __esmMin((() => {
}));
//#endregion
-//#region node_modules/.pnpm/diff@8.0.2/node_modules/diff/libesm/diff/sentence.js
+//#region node_modules/diff/libesm/diff/sentence.js
function isSentenceEndPunct(char) {
return char == "." || char == "!" || char == "?";
}
@@ -194524,7 +194576,7 @@ var init_sentence = __esmMin((() => {
}));
//#endregion
-//#region node_modules/.pnpm/diff@8.0.2/node_modules/diff/libesm/diff/css.js
+//#region node_modules/diff/libesm/diff/css.js
function diffCss(oldStr, newStr, options) {
return cssDiff.diff(oldStr, newStr, options);
}
@@ -194540,7 +194592,7 @@ var init_css = __esmMin((() => {
}));
//#endregion
-//#region node_modules/.pnpm/diff@8.0.2/node_modules/diff/libesm/diff/json.js
+//#region node_modules/diff/libesm/diff/json.js
function diffJson(oldStr, newStr, options) {
return jsonDiff.diff(oldStr, newStr, options);
}
@@ -194619,7 +194671,7 @@ var init_json = __esmMin((() => {
}));
//#endregion
-//#region node_modules/.pnpm/diff@8.0.2/node_modules/diff/libesm/diff/array.js
+//#region node_modules/diff/libesm/diff/array.js
function diffArrays(oldArr, newArr, options) {
return arrayDiff.diff(oldArr, newArr, options);
}
@@ -194641,7 +194693,7 @@ var init_array = __esmMin((() => {
}));
//#endregion
-//#region node_modules/.pnpm/diff@8.0.2/node_modules/diff/libesm/patch/line-endings.js
+//#region node_modules/diff/libesm/patch/line-endings.js
function unixToWin(patch) {
if (Array.isArray(patch)) {
return patch.map((p$3) => unixToWin(p$3));
@@ -194682,7 +194734,7 @@ function isWin(patch) {
var init_line_endings = __esmMin((() => {}));
//#endregion
-//#region node_modules/.pnpm/diff@8.0.2/node_modules/diff/libesm/patch/parse.js
+//#region node_modules/diff/libesm/patch/parse.js
/**
* Parses a patch into structured data, in the same structure returned by `structuredPatch`.
*
@@ -194794,7 +194846,7 @@ function parsePatch(uniDiff) {
var init_parse = __esmMin((() => {}));
//#endregion
-//#region node_modules/.pnpm/diff@8.0.2/node_modules/diff/libesm/util/distance-iterator.js
+//#region node_modules/diff/libesm/util/distance-iterator.js
function distance_iterator_default(start, minLine, maxLine) {
let wantForward = true, backwardExhausted = false, forwardExhausted = false, localOffset = 1;
return function iterator() {
@@ -194825,7 +194877,7 @@ function distance_iterator_default(start, minLine, maxLine) {
var init_distance_iterator = __esmMin((() => {}));
//#endregion
-//#region node_modules/.pnpm/diff@8.0.2/node_modules/diff/libesm/patch/apply.js
+//#region node_modules/diff/libesm/patch/apply.js
/**
* attempts to apply a unified diff patch.
*
@@ -195050,7 +195102,7 @@ var init_apply = __esmMin((() => {
}));
//#endregion
-//#region node_modules/.pnpm/diff@8.0.2/node_modules/diff/libesm/patch/reverse.js
+//#region node_modules/diff/libesm/patch/reverse.js
function reversePatch(structuredPatch$1) {
if (Array.isArray(structuredPatch$1)) {
return structuredPatch$1.map((patch) => reversePatch(patch)).reverse();
@@ -195082,7 +195134,7 @@ function reversePatch(structuredPatch$1) {
var init_reverse = __esmMin((() => {}));
//#endregion
-//#region node_modules/.pnpm/diff@8.0.2/node_modules/diff/libesm/patch/create.js
+//#region node_modules/diff/libesm/patch/create.js
function structuredPatch(oldFileName, newFileName, oldStr, newStr, oldHeader, newHeader, options) {
let optionsObj;
if (!options) {
@@ -195264,7 +195316,7 @@ var init_create = __esmMin((() => {
}));
//#endregion
-//#region node_modules/.pnpm/diff@8.0.2/node_modules/diff/libesm/convert/dmp.js
+//#region node_modules/diff/libesm/convert/dmp.js
/**
* converts a list of change objects to the format returned by Google's [diff-match-patch](https://github.com/google/diff-match-patch) library
*/
@@ -195287,7 +195339,7 @@ function convertChangesToDMP(changes) {
var init_dmp = __esmMin((() => {}));
//#endregion
-//#region node_modules/.pnpm/diff@8.0.2/node_modules/diff/libesm/convert/xml.js
+//#region node_modules/diff/libesm/convert/xml.js
/**
* converts a list of change objects to a serialized XML format
*/
@@ -195320,7 +195372,7 @@ function escapeHTML(s$5) {
var init_xml = __esmMin((() => {}));
//#endregion
-//#region node_modules/.pnpm/diff@8.0.2/node_modules/diff/libesm/index.js
+//#region node_modules/diff/libesm/index.js
var init_libesm = __esmMin((() => {
init_base();
init_character();
@@ -195339,7 +195391,7 @@ var init_libesm = __esmMin((() => {
}));
//#endregion
-//#region node_modules/.pnpm/@mariozechner+mini-lit@0.2.1_lit@3.3.1_tailwindcss@4.1.17/node_modules/@mariozechner/mini-lit/dist/Diff.js
+//#region node_modules/@mariozechner/mini-lit/dist/Diff.js
var Diff;
var init_Diff = __esmMin((() => {
init_libesm();
diff --git a/apps/macos/Sources/Clawdis/Utilities.swift b/apps/macos/Sources/Clawdis/Utilities.swift
index 41150eecb..5a3eeab5a 100644
--- a/apps/macos/Sources/Clawdis/Utilities.swift
+++ b/apps/macos/Sources/Clawdis/Utilities.swift
@@ -204,10 +204,10 @@ enum CLIInstaller {
}
enum CommandResolver {
- private static let projectRootDefaultsKey = "clawdis.relayProjectRootPath"
+ private static let projectRootDefaultsKey = "clawdis.gatewayProjectRootPath"
private static let helperName = "clawdis"
- static func relayEntrypoint(in root: URL) -> String? {
+ static func gatewayEntrypoint(in root: URL) -> String? {
let distEntry = root.appendingPathComponent("dist/index.js").path
if FileManager.default.isReadableFile(atPath: distEntry) { return distEntry }
let binEntry = root.appendingPathComponent("bin/clawdis.js").path
@@ -326,7 +326,7 @@ enum CommandResolver {
return [clawdisPath, subcommand] + extraArgs
}
- if let entry = self.relayEntrypoint(in: self.projectRoot()) {
+ if let entry = self.gatewayEntrypoint(in: self.projectRoot()) {
return self.makeRuntimeCommand(
runtime: runtime,
entrypoint: entry,
diff --git a/apps/macos/Tests/ClawdisIPCTests/CommandResolverTests.swift b/apps/macos/Tests/ClawdisIPCTests/CommandResolverTests.swift
index 56479600a..a2a302a92 100644
--- a/apps/macos/Tests/ClawdisIPCTests/CommandResolverTests.swift
+++ b/apps/macos/Tests/ClawdisIPCTests/CommandResolverTests.swift
@@ -26,8 +26,8 @@ import Testing
let clawdisPath = tmp.appendingPathComponent("node_modules/.bin/clawdis")
try self.makeExec(at: clawdisPath)
- let cmd = CommandResolver.clawdisCommand(subcommand: "relay")
- #expect(cmd.prefix(2).elementsEqual([clawdisPath.path, "relay"]))
+ let cmd = CommandResolver.clawdisCommand(subcommand: "gateway")
+ #expect(cmd.prefix(2).elementsEqual([clawdisPath.path, "gateway"]))
}
@Test func fallsBackToNodeAndScript() async throws {
diff --git a/docs/mac/child-process.md b/docs/mac/child-process.md
index 2719fdc99..38fcb7a31 100644
--- a/docs/mac/child-process.md
+++ b/docs/mac/child-process.md
@@ -31,7 +31,7 @@ Run the Node-based Clawdis/clawdis gateway as a direct child of the LSUIElement
- If you ever embed Node that *must* touch TCC, wrap that call in a tiny signed helper target inside the app bundle and have Node exec that helper instead of calling the API directly.
## Process manager design (Swift Subprocess)
-- Add a small `RelayProcessManager` (Swift) that owns:
+- Add a small `GatewayProcessManager` (Swift) that owns:
- `execution: Execution?` from `Swift Subprocess` to track the child.
- `start(config)` called when “Clawdis Active” flips ON:
- binary: host Node running the bundled gateway under `Clawdis.app/Contents/Resources/Gateway/`
@@ -41,8 +41,8 @@ Run the Node-based Clawdis/clawdis gateway as a direct child of the LSUIElement
- restart: optional linear/backoff restart if exit was non-zero and Active is still true
- `stop()` called when Active flips OFF or app terminates: cancel the execution and `waitUntilExit`.
- Wire SwiftUI toggle:
- - ON: `RelayProcessManager.start(...)`
- - OFF: `RelayProcessManager.stop()` (no launchctl calls in this mode)
+- ON: `GatewayProcessManager.start(...)`
+- OFF: `GatewayProcessManager.stop()` (no launchctl calls in this mode)
- Keep the existing `LaunchdManager` around so we can switch back if needed; the toggle can choose between launchd or child mode with a flag if we want both.
## Packaging and signing
@@ -67,5 +67,5 @@ Run the Node-based Clawdis/clawdis gateway as a direct child of the LSUIElement
## Decision snapshot (current recommendation)
- Keep all TCC surfaces in the Swift app/XPC.
-- Implement `RelayProcessManager` with Swift Subprocess to start/stop the gateway on the “Clawdis Active” toggle.
+- Implement `GatewayProcessManager` with Swift Subprocess to start/stop the gateway on the “Clawdis Active” toggle.
- Maintain the launchd path as a fallback for uptime/login persistence until child-mode proves stable.
diff --git a/docs/refactor/web-relay-troubleshooting.md b/docs/refactor/web-relay-troubleshooting.md
deleted file mode 100644
index 9d2ce3783..000000000
--- a/docs/refactor/web-relay-troubleshooting.md
+++ /dev/null
@@ -1,37 +0,0 @@
----
-summary: "Troubleshooting guide for the web gateway/Baileys relay"
-read_when:
- - Diagnosing web relay socket or login issues
----
-# Web Gateway Troubleshooting (Nov 26, 2025)
-
-## Symptoms & quick fixes
-- **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 gateway.
-- **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`.
-- **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.
-
-## Helpful commands
-- Start gateway web-only: `pnpm clawdis gateway --provider web --verbose`
-- Show who is linked: `pnpm clawdis gateway --provider web --verbose` (first line prints the linked E.164)
-- Logout (clear creds): `pnpm clawdis logout`
-- Relink: `pnpm clawdis login --provider web`
-- Tail logs (default): `tail -f /tmp/clawdis/clawdis.log`
-
-## Reading the logs
-- `web-reconnect`: close reasons, retry/backoff, max-attempt exit.
-- `web-heartbeat`: connectionId, messagesHandled, authAgeMs, uptimeMs (every 60s by default).
-- `web-auto-reply`: inbound/outbound message records with correlation IDs.
-
-## When to tweak knobs
-- High churn networks: increase `web.reconnect.maxAttempts` or `--web-retries`.
-- Slow links: raise `--web-retry-max` to give more headroom before bailing.
-- Chatty monitors: increase `--web-heartbeat` interval if log volume is high.
-
-## If it keeps failing
-1) `clawdis logout` → `clawdis login --provider web` (fresh QR link).
-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.
-4) If status is 515, let the client restart once after pairing (already handled automatically).
-5) Capture the last `web-reconnect` entry and the status code before escalating.
diff --git a/scripts/clawlog.sh b/scripts/clawlog.sh
index b0f8e97f5..86852ea18 100755
--- a/scripts/clawlog.sh
+++ b/scripts/clawlog.sh
@@ -62,7 +62,7 @@ LOG FLOW ARCHITECTURE:
LOG CATEGORIES (examples):
• voicewake - Voice wake detection/test harness
- • relay - Relay process manager
+ • gateway - Gateway process manager
• xpc - XPC service calls
• notifications - Notification helper
• screenshot - Screenshotter
diff --git a/scripts/codesign-mac-app.sh b/scripts/codesign-mac-app.sh
index 18c59bc98..34bf93ad9 100755
--- a/scripts/codesign-mac-app.sh
+++ b/scripts/codesign-mac-app.sh
@@ -82,10 +82,10 @@ if [ -f "$APP_BUNDLE/Contents/MacOS/ClawdisCLI" ]; then
echo "Signing CLI helper"; sign_item "$APP_BUNDLE/Contents/MacOS/ClawdisCLI"
fi
-# Sign bundled relay payload (native addons, libvips dylibs)
+# Sign bundled gateway payload (native addons, libvips dylibs)
if [ -d "$APP_BUNDLE/Contents/Resources/Relay" ]; then
find "$APP_BUNDLE/Contents/Resources/Relay" -type f \( -name "*.node" -o -name "*.dylib" \) -print0 | while IFS= read -r -d '' f; do
- echo "Signing relay payload: $f"; sign_item "$f"
+ echo "Signing gateway payload: $f"; sign_item "$f"
done
fi
diff --git a/scripts/package-mac-app.sh b/scripts/package-mac-app.sh
index 7577337de..0a0014be6 100755
--- a/scripts/package-mac-app.sh
+++ b/scripts/package-mac-app.sh
@@ -118,8 +118,8 @@ rm -rf "$APP_ROOT/Contents/Resources/WebChat/vendor/pdfjs-dist/legacy"
RELAY_DIR="$APP_ROOT/Contents/Resources/Relay"
-if [[ "${SKIP_RELAY_PACKAGE:-0}" != "1" ]]; then
- echo "🧰 Staging relay payload (dist + node_modules; expects system Node ≥22)"
+if [[ "${SKIP_GATEWAY_PACKAGE:-0}" != "1" ]]; then
+ echo "🧰 Staging gateway payload (dist + node_modules; expects system Node ≥22)"
rsync -a --delete --exclude "Clawdis.app" "$ROOT_DIR/dist/" "$RELAY_DIR/dist/"
cp "$ROOT_DIR/package.json" "$RELAY_DIR/"
cp "$ROOT_DIR/pnpm-lock.yaml" "$RELAY_DIR/"
@@ -170,7 +170,7 @@ if [[ "${SKIP_RELAY_PACKAGE:-0}" != "1" ]]; then
"$RELAY_DIR/node_modules"/{vite,rolldown,vitest,ts-node,ts-node-dev,typescript,@types,docx-preview,jszip,lucide,ollama} 2>/dev/null || true
rm -rf "$TMP_DEPLOY"
else
- echo "🧰 Skipping relay payload packaging (SKIP_RELAY_PACKAGE=1)"
+ echo "🧰 Skipping gateway payload packaging (SKIP_GATEWAY_PACKAGE=1)"
fi
if [ -f "$CLI_BIN" ]; then
diff --git a/scripts/restart-mac.sh b/scripts/restart-mac.sh
index 538be6448..ed8a4285c 100755
--- a/scripts/restart-mac.sh
+++ b/scripts/restart-mac.sh
@@ -59,8 +59,8 @@ run_step "bundle webchat" bash -lc "cd '${ROOT_DIR}' && pnpm webchat:bundle"
run_step "clean build cache" bash -lc "cd '${ROOT_DIR}/apps/macos' && rm -rf .build .build-swift .swiftpm 2>/dev/null || true"
run_step "swift build" bash -lc "cd '${ROOT_DIR}/apps/macos' && swift build -q --product Clawdis"
-# 3) Package app (skip TS + relay staging; rely on global/custom install for relay JS).
-run_step "package app" bash -lc "cd '${ROOT_DIR}' && SKIP_TSC=1 SKIP_RELAY_PACKAGE=1 '${ROOT_DIR}/scripts/package-mac-app.sh'"
+# 3) Package app (skip TS + gateway staging; rely on global/custom install for gateway JS).
+run_step "package app" bash -lc "cd '${ROOT_DIR}' && SKIP_TSC=1 SKIP_GATEWAY_PACKAGE=1 '${ROOT_DIR}/scripts/package-mac-app.sh'"
choose_app_bundle() {
if [[ -n "${APP_BUNDLE}" && -d "${APP_BUNDLE}" ]]; then
diff --git a/src/auto-reply/command-reply.ts b/src/auto-reply/command-reply.ts
index cd5d5b924..2fb2e0f87 100644
--- a/src/auto-reply/command-reply.ts
+++ b/src/auto-reply/command-reply.ts
@@ -8,7 +8,7 @@ import type {
} from "@mariozechner/pi-ai";
import { piSpec } from "../agents/pi.js";
import type { AgentMeta, AgentToolResult } from "../agents/types.js";
-import type { WarelayConfig } from "../config/config.js";
+import type { ClawdisConfig } from "../config/config.js";
import { isVerbose, logVerbose } from "../globals.js";
import { emitAgentEvent } from "../infra/agent-events.js";
import { logError } from "../logger.js";
@@ -141,7 +141,7 @@ function extractAssistantTextLoosely(raw: string): string | undefined {
return last ? last.replace(/\\n/g, "\n").trim() : undefined;
}
-type CommandReplyConfig = NonNullable
["reply"] & {
+type CommandReplyConfig = NonNullable["reply"] & {
mode: "command";
};
diff --git a/src/auto-reply/reply.ts b/src/auto-reply/reply.ts
index 77a51bce2..ff4122564 100644
--- a/src/auto-reply/reply.ts
+++ b/src/auto-reply/reply.ts
@@ -3,7 +3,7 @@ import crypto from "node:crypto";
import { lookupContextTokens } from "../agents/context.js";
import { DEFAULT_CONTEXT_TOKENS, DEFAULT_MODEL } from "../agents/defaults.js";
import { resolveBundledPiBinary } from "../agents/pi-path.js";
-import { loadConfig, type WarelayConfig } from "../config/config.js";
+import { loadConfig, type ClawdisConfig } from "../config/config.js";
import {
DEFAULT_IDLE_MINUTES,
DEFAULT_RESET_TRIGGER,
@@ -15,7 +15,7 @@ import {
} from "../config/sessions.js";
import { isVerbose, logVerbose } from "../globals.js";
import { buildProviderSummary } from "../infra/provider-summary.js";
-import { triggerWarelayRestart } from "../infra/restart.js";
+import { triggerClawdisRestart } from "../infra/restart.js";
import { drainSystemEvents } from "../infra/system-events.js";
import { defaultRuntime } from "../runtime.js";
import { resolveHeartbeatSeconds } from "../web/reconnect.js";
@@ -42,7 +42,7 @@ const ABORT_TRIGGERS = new Set(["stop", "esc", "abort", "wait", "exit"]);
const ABORT_MEMORY = new Map();
const SYSTEM_MARK = "⚙️";
-type ReplyConfig = NonNullable["reply"];
+type ReplyConfig = NonNullable["reply"];
export function extractThinkDirective(body?: string): {
cleaned: string;
@@ -112,7 +112,7 @@ function stripStructuralPrefixes(text: string): string {
function stripMentions(
text: string,
ctx: MsgContext,
- cfg: WarelayConfig | undefined,
+ cfg: ClawdisConfig | undefined,
): string {
let result = text;
const patterns = cfg?.inbound?.groupChat?.mentionPatterns ?? [];
@@ -161,7 +161,7 @@ function makeDefaultPiReply(): ReplyConfig {
export async function getReplyFromConfig(
ctx: MsgContext,
opts?: GetReplyOptions,
- configOverride?: WarelayConfig,
+ configOverride?: ClawdisConfig,
): Promise {
// Choose reply from config: static text or external command stdout.
const cfg = configOverride ?? loadConfig();
@@ -503,7 +503,7 @@ export async function getReplyFromConfig(
rawBodyNormalized === "restart" ||
rawBodyNormalized.startsWith("/restart ")
) {
- triggerWarelayRestart();
+ triggerClawdisRestart();
cleanupTyping();
return {
text: "⚙️ Restarting clawdis via launchctl; give me a few seconds to come back online.",
diff --git a/src/auto-reply/status.ts b/src/auto-reply/status.ts
index f938ef6c8..bc9d083c6 100644
--- a/src/auto-reply/status.ts
+++ b/src/auto-reply/status.ts
@@ -5,11 +5,11 @@ import path from "node:path";
import { lookupContextTokens } from "../agents/context.js";
import { DEFAULT_CONTEXT_TOKENS, DEFAULT_MODEL } from "../agents/defaults.js";
-import type { WarelayConfig } from "../config/config.js";
+import type { ClawdisConfig } from "../config/config.js";
import type { SessionEntry, SessionScope } from "../config/sessions.js";
import type { ThinkLevel, VerboseLevel } from "./thinking.js";
-type ReplyConfig = NonNullable["reply"];
+type ReplyConfig = NonNullable["reply"];
type StatusArgs = {
reply: ReplyConfig;
diff --git a/src/auto-reply/transcription.ts b/src/auto-reply/transcription.ts
index 85232de27..4cecb8f95 100644
--- a/src/auto-reply/transcription.ts
+++ b/src/auto-reply/transcription.ts
@@ -3,7 +3,7 @@ import fs from "node:fs/promises";
import os from "node:os";
import path from "node:path";
-import type { WarelayConfig } from "../config/config.js";
+import type { ClawdisConfig } from "../config/config.js";
import { isVerbose, logVerbose } from "../globals.js";
import { runExec } from "../process/exec.js";
import type { RuntimeEnv } from "../runtime.js";
@@ -14,7 +14,7 @@ export function isAudio(mediaType?: string | null) {
}
export async function transcribeInboundAudio(
- cfg: WarelayConfig,
+ cfg: ClawdisConfig,
ctx: MsgContext,
runtime: RuntimeEnv,
): Promise<{ text: string } | undefined> {
diff --git a/src/cli/program.ts b/src/cli/program.ts
index c64adaa91..2b2f0d963 100644
--- a/src/cli/program.ts
+++ b/src/cli/program.ts
@@ -279,7 +279,7 @@ Examples:
});
program
.command("gateway")
- .description("Run the WebSocket Gateway (replaces relay)")
+ .description("Run the WebSocket Gateway")
.option("--port ", "Port for the gateway WebSocket", "18789")
.option(
"--token ",
diff --git a/src/commands/agent.test.ts b/src/commands/agent.test.ts
index 4597899ae..3fefa054b 100644
--- a/src/commands/agent.test.ts
+++ b/src/commands/agent.test.ts
@@ -11,7 +11,7 @@ import {
vi,
} from "vitest";
import * as commandReply from "../auto-reply/command-reply.js";
-import type { WarelayConfig } from "../config/config.js";
+import type { ClawdisConfig } from "../config/config.js";
import * as configModule from "../config/config.js";
import type { RuntimeEnv } from "../runtime.js";
import { agentCommand } from "./agent.js";
@@ -36,7 +36,7 @@ function makeStorePath() {
function mockConfig(
storePath: string,
- replyOverrides?: Partial["reply"]>,
+ replyOverrides?: Partial["reply"]>,
) {
configSpy.mockReturnValue({
inbound: {
diff --git a/src/commands/agent.ts b/src/commands/agent.ts
index c4d89da56..a2d522b70 100644
--- a/src/commands/agent.ts
+++ b/src/commands/agent.ts
@@ -12,7 +12,7 @@ import {
type VerboseLevel,
} from "../auto-reply/thinking.js";
import { type CliDeps, createDefaultDeps } from "../cli/deps.js";
-import { loadConfig, type WarelayConfig } from "../config/config.js";
+import { loadConfig, type ClawdisConfig } from "../config/config.js";
import {
DEFAULT_IDLE_MINUTES,
loadSessionStore,
@@ -50,7 +50,7 @@ type SessionResolution = {
persistedVerbose?: VerboseLevel;
};
-function assertCommandConfig(cfg: WarelayConfig) {
+function assertCommandConfig(cfg: ClawdisConfig) {
const reply = cfg.inbound?.reply;
if (!reply || reply.mode !== "command" || !reply.command?.length) {
throw new Error(
@@ -58,14 +58,14 @@ function assertCommandConfig(cfg: WarelayConfig) {
);
}
return reply as NonNullable<
- NonNullable["reply"]
+ NonNullable["reply"]
> & { mode: "command"; command: string[] };
}
function resolveSession(opts: {
to?: string;
sessionId?: string;
- replyCfg: NonNullable["reply"]>;
+ replyCfg: NonNullable["reply"]>;
}): SessionResolution {
const sessionCfg = opts.replyCfg?.session;
const scope = sessionCfg?.scope ?? "per-sender";
diff --git a/src/commands/send.ts b/src/commands/send.ts
index dff6c26ca..153db86ee 100644
--- a/src/commands/send.ts
+++ b/src/commands/send.ts
@@ -53,12 +53,12 @@ export async function sendCommand(
return;
}
- // Try to send via IPC to running relay first (avoids Signal session corruption)
+ // Try to send via IPC to running gateway first (avoids Signal session corruption)
const ipcResult = await sendViaIpc(opts.to, opts.message, opts.media);
if (ipcResult) {
if (ipcResult.success) {
runtime.log(
- success(`✅ Sent via relay IPC. Message ID: ${ipcResult.messageId}`),
+ success(`✅ Sent via gateway IPC. Message ID: ${ipcResult.messageId}`),
);
if (opts.json) {
runtime.log(
@@ -77,7 +77,7 @@ export async function sendCommand(
}
return;
}
- // IPC failed but relay is running - warn and fall back
+ // IPC failed but gateway is running - warn and fall back
runtime.log(
info(
`IPC send failed (${ipcResult.error}), falling back to direct connection`,
diff --git a/src/config/config.ts b/src/config/config.ts
index 1ba08031d..2f2719a78 100644
--- a/src/config/config.ts
+++ b/src/config/config.ts
@@ -66,7 +66,7 @@ export type GroupChatConfig = {
historyLimit?: number;
};
-export type WarelayConfig = {
+export type ClawdisConfig = {
logging?: LoggingConfig;
inbound?: {
allowFrom?: string[]; // E.164 numbers allowed to trigger auto-reply (without whatsapp:)
@@ -179,7 +179,7 @@ const ReplySchema = z
},
);
-const WarelaySchema = z.object({
+const ClawdisSchema = z.object({
logging: z
.object({
level: z
@@ -252,7 +252,7 @@ const WarelaySchema = z.object({
.optional(),
});
-export function loadConfig(): WarelayConfig {
+export function loadConfig(): ClawdisConfig {
// Read config file (JSON5) if present.
const configPath = CONFIG_PATH_CLAWDIS;
try {
@@ -260,7 +260,7 @@ export function loadConfig(): WarelayConfig {
const raw = fs.readFileSync(configPath, "utf-8");
const parsed = JSON5.parse(raw);
if (typeof parsed !== "object" || parsed === null) return {};
- const validated = WarelaySchema.safeParse(parsed);
+ const validated = ClawdisSchema.safeParse(parsed);
if (!validated.success) {
console.error("Invalid config:");
for (const iss of validated.error.issues) {
@@ -268,7 +268,7 @@ export function loadConfig(): WarelayConfig {
}
return {};
}
- return validated.data as WarelayConfig;
+ return validated.data as ClawdisConfig;
} catch (err) {
console.error(`Failed to read config at ${configPath}`, err);
return {};
diff --git a/src/infra/provider-summary.ts b/src/infra/provider-summary.ts
index 82bda46aa..e6f673379 100644
--- a/src/infra/provider-summary.ts
+++ b/src/infra/provider-summary.ts
@@ -1,5 +1,5 @@
import chalk from "chalk";
-import { loadConfig, type WarelayConfig } from "../config/config.js";
+import { loadConfig, type ClawdisConfig } from "../config/config.js";
import { normalizeE164 } from "../utils.js";
import {
getWebAuthAgeMs,
@@ -10,7 +10,7 @@ import {
const DEFAULT_WEBCHAT_PORT = 18788;
export async function buildProviderSummary(
- cfg?: WarelayConfig,
+ cfg?: ClawdisConfig,
): Promise {
const effective = cfg ?? loadConfig();
const lines: string[] = [];
diff --git a/src/infra/relay-lock.test.ts b/src/infra/relay-lock.test.ts
deleted file mode 100644
index 4e7b2eed4..000000000
--- a/src/infra/relay-lock.test.ts
+++ /dev/null
@@ -1,34 +0,0 @@
-import fs from "node:fs";
-import os from "node:os";
-import path from "node:path";
-
-import { describe, expect, it } from "vitest";
-
-import { acquireRelayLock, RelayLockError } from "./relay-lock.js";
-
-const newLockPath = () =>
- path.join(
- os.tmpdir(),
- `clawdis-relay-lock-test-${process.pid}-${Math.random().toString(16).slice(2)}.sock`,
- );
-
-describe("relay-lock", () => {
- it("prevents concurrent relay instances and releases cleanly", async () => {
- const lockPath = newLockPath();
-
- const release1 = await acquireRelayLock(lockPath);
- expect(fs.existsSync(lockPath)).toBe(true);
-
- await expect(acquireRelayLock(lockPath)).rejects.toBeInstanceOf(
- RelayLockError,
- );
-
- await release1();
- expect(fs.existsSync(lockPath)).toBe(false);
-
- // After release, lock can be reacquired.
- const release2 = await acquireRelayLock(lockPath);
- await release2();
- expect(fs.existsSync(lockPath)).toBe(false);
- });
-});
diff --git a/src/infra/relay-lock.ts b/src/infra/relay-lock.ts
deleted file mode 100644
index 7d37faef6..000000000
--- a/src/infra/relay-lock.ts
+++ /dev/null
@@ -1,102 +0,0 @@
-import fs from "node:fs";
-import net from "node:net";
-import os from "node:os";
-import path from "node:path";
-
-const DEFAULT_LOCK_PATH = path.join(os.tmpdir(), "clawdis-relay.lock");
-
-export class RelayLockError extends Error {}
-
-type ReleaseFn = () => Promise;
-
-/**
- * Acquire an exclusive single-instance lock for the relay using a Unix domain socket.
- *
- * Why a socket? If the process crashes or is SIGKILLed, the socket file remains but
- * the next start will detect ECONNREFUSED when connecting and clean the stale path
- * before retrying. This keeps the lock self-healing without manual pidfile cleanup.
- */
-export async function acquireRelayLock(
- lockPath = DEFAULT_LOCK_PATH,
-): Promise {
- // Fast path: try to listen on the lock path.
- const attemptListen = (): Promise =>
- new Promise((resolve, reject) => {
- const server = net.createServer();
-
- server.once("error", async (err: NodeJS.ErrnoException) => {
- if (err.code !== "EADDRINUSE") {
- reject(new RelayLockError(`lock listen failed: ${err.message}`));
- return;
- }
-
- // Something is already bound. Try to connect to see if it is alive.
- const client = net.connect({ path: lockPath });
-
- client.once("connect", () => {
- client.destroy();
- reject(
- new RelayLockError("another relay instance is already running"),
- );
- });
-
- client.once("error", (connErr: NodeJS.ErrnoException) => {
- // Nothing is listening -> stale socket file. Remove and retry once.
- if (connErr.code === "ECONNREFUSED" || connErr.code === "ENOENT") {
- try {
- fs.rmSync(lockPath, { force: true });
- } catch (rmErr) {
- reject(
- new RelayLockError(
- `failed to clean stale lock at ${lockPath}: ${String(rmErr)}`,
- ),
- );
- return;
- }
- attemptListen().then(resolve, reject);
- return;
- }
-
- reject(
- new RelayLockError(
- `failed to connect to existing lock (${lockPath}): ${connErr.message}`,
- ),
- );
- });
- });
-
- server.listen(lockPath, () => resolve(server));
- });
-
- const server = await attemptListen();
-
- let released = false;
- const release = async (): Promise => {
- if (released) return;
- released = true;
- await new Promise((resolve) => server.close(() => resolve()));
- try {
- fs.rmSync(lockPath, { force: true });
- } catch {
- /* ignore */
- }
- };
-
- const cleanupSignals: NodeJS.Signals[] = ["SIGINT", "SIGTERM", "SIGHUP"];
- const handleSignal = async () => {
- await release();
- process.exit(0);
- };
-
- for (const sig of cleanupSignals) {
- process.once(sig, () => {
- void handleSignal();
- });
- }
- process.once("exit", () => {
- // Exit handler must be sync-safe; release is async but close+rm are fast.
- void release();
- });
-
- return release;
-}
diff --git a/src/infra/restart.ts b/src/infra/restart.ts
index 73f6d6515..275f5c1eb 100644
--- a/src/infra/restart.ts
+++ b/src/infra/restart.ts
@@ -2,9 +2,8 @@ import { spawn } from "node:child_process";
const DEFAULT_LAUNCHD_LABEL = "com.steipete.clawdis";
-export function triggerWarelayRestart(): void {
+export function triggerClawdisRestart(): void {
const label =
- process.env.WARELAY_LAUNCHD_LABEL ||
process.env.CLAWDIS_LAUNCHD_LABEL ||
DEFAULT_LAUNCHD_LABEL;
const uid =
diff --git a/src/infra/system-presence.ts b/src/infra/system-presence.ts
index 4ef3264b4..a8be85aae 100644
--- a/src/infra/system-presence.ts
+++ b/src/infra/system-presence.ts
@@ -56,7 +56,7 @@ function initSelfPresence() {
function ensureSelfPresence() {
// If the map was somehow cleared (e.g., hot reload or a new worker spawn that
// skipped module evaluation), re-seed with a local entry so UIs always show
- // at least the current relay.
+ // at least the current gateway.
if (entries.size === 0) {
initSelfPresence();
}
diff --git a/src/infra/tailscale.ts b/src/infra/tailscale.ts
index 220e9c329..7500deba1 100644
--- a/src/infra/tailscale.ts
+++ b/src/infra/tailscale.ts
@@ -150,7 +150,7 @@ export async function ensureFunnel(
);
runtime.error(
info(
- "Tip: Funnel is optional for CLAWDIS. You can keep running the web relay without it: `pnpm clawdis gateway`",
+ "Tip: Funnel is optional for CLAWDIS. You can keep running the web gateway without it: `pnpm clawdis gateway`",
),
);
if (isVerbose()) {
diff --git a/src/logging.ts b/src/logging.ts
index 8ae9e6e12..b4af3b341 100644
--- a/src/logging.ts
+++ b/src/logging.ts
@@ -3,7 +3,7 @@ import path from "node:path";
import util from "node:util";
import { Logger as TsLogger } from "tslog";
-import { loadConfig, type WarelayConfig } from "./config/config.js";
+import { loadConfig, type ClawdisConfig } from "./config/config.js";
import { isVerbose } from "./globals.js";
// Pin to /tmp so mac Debug UI and docs match; os.tmpdir() can be a per-user
@@ -55,7 +55,7 @@ function normalizeLevel(level?: string): Level {
}
function resolveSettings(): ResolvedSettings {
- const cfg: WarelayConfig["logging"] | undefined =
+ const cfg: ClawdisConfig["logging"] | undefined =
overrideSettings ?? loadConfig().logging;
const level = normalizeLevel(cfg?.level);
const file = cfg?.file ?? defaultRollingPathForToday();
diff --git a/src/process/tau-rpc.ts b/src/process/tau-rpc.ts
index 0c14cdbb3..8578d1968 100644
--- a/src/process/tau-rpc.ts
+++ b/src/process/tau-rpc.ts
@@ -131,7 +131,7 @@ class TauRpcClient {
if (!ok) child.stdin.once("drain", () => resolve());
});
return await new Promise((resolve, reject) => {
- // Hard cap to avoid stuck relays; resets on every line received.
+ // Hard cap to avoid stuck gateways; resets on every line received.
const capMs = Math.min(timeoutMs, 5 * 60 * 1000);
const timer = setTimeout(() => {
this.pending = undefined;
diff --git a/src/telegram/monitor.ts b/src/telegram/monitor.ts
index 3c5492c99..cfe6333b7 100644
--- a/src/telegram/monitor.ts
+++ b/src/telegram/monitor.ts
@@ -20,7 +20,7 @@ export async function monitorTelegramProvider(opts: MonitorTelegramOpts = {}) {
const token = (opts.token ?? process.env.TELEGRAM_BOT_TOKEN)?.trim();
if (!token) {
throw new Error(
- "TELEGRAM_BOT_TOKEN or telegram.botToken is required for Telegram relay",
+ "TELEGRAM_BOT_TOKEN or telegram.botToken is required for Telegram gateway",
);
}
diff --git a/src/web/auto-reply.test.ts b/src/web/auto-reply.test.ts
index 05b67be44..2071f6302 100644
--- a/src/web/auto-reply.test.ts
+++ b/src/web/auto-reply.test.ts
@@ -6,7 +6,7 @@ import path from "node:path";
import sharp from "sharp";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
-import type { WarelayConfig } from "../config/config.js";
+import type { ClawdisConfig } from "../config/config.js";
import { resetLogger, setLoggerOverride } from "../logging.js";
import * as commandQueue from "../process/command-queue.js";
import {
@@ -65,7 +65,7 @@ describe("heartbeat helpers", () => {
});
it("resolves heartbeat minutes with default and overrides", () => {
- const cfgBase: WarelayConfig = {
+ const cfgBase: ClawdisConfig = {
inbound: {
reply: { mode: "command" as const },
},
@@ -94,7 +94,7 @@ describe("resolveHeartbeatRecipients", () => {
it("returns the sole session recipient", async () => {
const now = Date.now();
const store = await makeSessionStore({ "+1000": { updatedAt: now } });
- const cfg: WarelayConfig = {
+ const cfg: ClawdisConfig = {
inbound: {
allowFrom: ["+1999"],
reply: { mode: "command", session: { store: store.storePath } },
@@ -112,7 +112,7 @@ describe("resolveHeartbeatRecipients", () => {
"+1000": { updatedAt: now },
"+2000": { updatedAt: now - 10 },
});
- const cfg: WarelayConfig = {
+ const cfg: ClawdisConfig = {
inbound: {
allowFrom: ["+1999"],
reply: { mode: "command", session: { store: store.storePath } },
@@ -126,7 +126,7 @@ describe("resolveHeartbeatRecipients", () => {
it("filters wildcard allowFrom when no sessions exist", async () => {
const store = await makeSessionStore({});
- const cfg: WarelayConfig = {
+ const cfg: ClawdisConfig = {
inbound: {
allowFrom: ["*"],
reply: { mode: "command", session: { store: store.storePath } },
@@ -141,7 +141,7 @@ describe("resolveHeartbeatRecipients", () => {
it("merges sessions and allowFrom when --all is set", async () => {
const now = Date.now();
const store = await makeSessionStore({ "+1000": { updatedAt: now } });
- const cfg: WarelayConfig = {
+ const cfg: ClawdisConfig = {
inbound: {
allowFrom: ["+1999"],
reply: { mode: "command", session: { store: store.storePath } },
@@ -162,7 +162,7 @@ describe("partial reply gating", () => {
const replyResolver = vi.fn().mockResolvedValue({ text: "final reply" });
- const mockConfig: WarelayConfig = {
+ const mockConfig: ClawdisConfig = {
inbound: {
reply: { mode: "command" },
allowFrom: ["*"],
@@ -342,7 +342,7 @@ describe("runWebHeartbeatOnce", () => {
const replyResolver = vi.fn().mockResolvedValue({ text: HEARTBEAT_TOKEN });
const runtime = { log: vi.fn(), error: vi.fn(), exit: vi.fn() } as never;
- const cfg: WarelayConfig = {
+ const cfg: ClawdisConfig = {
inbound: {
allowFrom: ["+4367"],
reply: {
@@ -385,7 +385,7 @@ describe("runWebHeartbeatOnce", () => {
}));
const resolver = vi.fn(async () => ({ text: HEARTBEAT_TOKEN }));
- const cfg: WarelayConfig = {
+ const cfg: ClawdisConfig = {
inbound: {
allowFrom: ["+1999"],
reply: {
diff --git a/src/web/auto-reply.ts b/src/web/auto-reply.ts
index a6c11f263..8faa4e3d9 100644
--- a/src/web/auto-reply.ts
+++ b/src/web/auto-reply.ts
@@ -41,7 +41,7 @@ export function setHeartbeatsEnabled(enabled: boolean) {
}
/**
- * Send a message via IPC if relay is running, otherwise fall back to direct.
+ * Send a message via IPC if gateway is running, otherwise fall back to direct.
* This avoids Signal session corruption from multiple Baileys connections.
*/
async function sendWithIpcFallback(
@@ -52,7 +52,7 @@ async function sendWithIpcFallback(
const ipcResult = await sendViaIpc(to, message, opts.mediaUrl);
if (ipcResult?.success && ipcResult.messageId) {
if (opts.verbose) {
- console.log(info(`Sent via relay IPC (avoiding session corruption)`));
+ console.log(info(`Sent via gateway IPC (avoiding session corruption)`));
}
return { messageId: ipcResult.messageId, toJid: `${to}@s.whatsapp.net` };
}
@@ -720,7 +720,7 @@ export async function monitorWebProvider(
);
// Avoid noisy MaxListenersExceeded warnings in test environments where
- // multiple relay instances may be constructed.
+ // multiple gateway instances may be constructed.
const currentMaxListeners = process.getMaxListeners?.() ?? 10;
if (process.setMaxListeners && currentMaxListeners < 50) {
process.setMaxListeners(50);
@@ -1021,7 +1021,7 @@ export async function monitorWebProvider(
// Surface a concise connection event for the next main-session turn/heartbeat.
const { e164: selfE164 } = readWebSelfId();
enqueueSystemEvent(
- `WhatsApp relay connected${selfE164 ? ` as ${selfE164}` : ""}.`,
+ `WhatsApp gateway connected${selfE164 ? ` as ${selfE164}` : ""}.`,
);
// Start IPC server so `clawdis send` can use this connection
@@ -1099,10 +1099,10 @@ export async function monitorWebProvider(
if (minutesSinceLastMessage && minutesSinceLastMessage > 30) {
heartbeatLogger.warn(
logData,
- "⚠️ web relay heartbeat - no messages in 30+ minutes",
+ "⚠️ web gateway heartbeat - no messages in 30+ minutes",
);
} else {
- heartbeatLogger.info(logData, "web relay heartbeat");
+ heartbeatLogger.info(logData, "web gateway heartbeat");
}
}, heartbeatSeconds * 1000);
@@ -1398,7 +1398,7 @@ export async function monitorWebProvider(
);
enqueueSystemEvent(
- `WhatsApp relay disconnected (status ${status ?? "unknown"})`,
+ `WhatsApp gateway disconnected (status ${status ?? "unknown"})`,
);
if (loggedOut) {
diff --git a/src/web/inbound.ts b/src/web/inbound.ts
index cae068285..a20d4b8a9 100644
--- a/src/web/inbound.ts
+++ b/src/web/inbound.ts
@@ -64,7 +64,7 @@ export async function monitorWebInbox(options: {
onCloseResolve = resolve;
});
try {
- // Advertise that the relay is online right after connecting.
+ // Advertise that the gateway is online right after connecting.
await sock.sendPresenceUpdate("available");
if (isVerbose()) logVerbose("Sent global 'available' presence on connect");
} catch (err) {
diff --git a/src/web/ipc.ts b/src/web/ipc.ts
index bd229f478..7e95b4e70 100644
--- a/src/web/ipc.ts
+++ b/src/web/ipc.ts
@@ -1,7 +1,7 @@
/**
- * IPC server for clawdis relay.
+ * IPC server for clawdis gateway.
*
- * When the relay is running, it starts a Unix socket server that allows
+ * When the gateway is running, it starts a Unix socket server that allows
* `clawdis send` and `clawdis heartbeat` to send messages through the
* existing WhatsApp connection instead of creating new ones.
*
@@ -40,7 +40,7 @@ type SendHandler = (
let server: net.Server | null = null;
/**
- * Start the IPC server. Called by the relay when it starts.
+ * Start the IPC server. Called by the gateway when it starts.
*/
export function startIpcServer(sendHandler: SendHandler): void {
const logger = getChildLogger({ module: "ipc-server" });
@@ -126,7 +126,7 @@ export function startIpcServer(sendHandler: SendHandler): void {
}
/**
- * Stop the IPC server. Called when relay shuts down.
+ * Stop the IPC server. Called when gateway shuts down.
*/
export function stopIpcServer(): void {
if (server) {
@@ -141,7 +141,7 @@ export function stopIpcServer(): void {
}
/**
- * Check if the relay IPC server is running.
+ * Check if the gateway IPC server is running.
*/
export function isRelayRunning(): boolean {
try {
@@ -154,8 +154,8 @@ export function isRelayRunning(): boolean {
}
/**
- * Send a message through the running relay's IPC.
- * Returns null if relay is not running.
+ * Send a message through the running gateway's IPC.
+ * Returns null if gateway is not running.
*/
export async function sendViaIpc(
to: string,
@@ -214,7 +214,7 @@ export async function sendViaIpc(
if (!resolved) {
resolved = true;
clearTimeout(timeout);
- // Socket exists but can't connect - relay might have crashed
+ // Socket exists but can't connect - gateway might have crashed
resolve(null);
}
});
diff --git a/src/web/reconnect.test.ts b/src/web/reconnect.test.ts
index 3d7d548cf..19ecb71e0 100644
--- a/src/web/reconnect.test.ts
+++ b/src/web/reconnect.test.ts
@@ -1,6 +1,6 @@
import { describe, expect, it } from "vitest";
-import type { WarelayConfig } from "../config/config.js";
+import type { ClawdisConfig } from "../config/config.js";
import {
computeBackoff,
DEFAULT_HEARTBEAT_SECONDS,
@@ -11,7 +11,7 @@ import {
} from "./reconnect.js";
describe("web reconnect helpers", () => {
- const cfg: WarelayConfig = {};
+ const cfg: ClawdisConfig = {};
it("resolves sane reconnect defaults with clamps", () => {
const policy = resolveReconnectPolicy(cfg, {
diff --git a/src/web/reconnect.ts b/src/web/reconnect.ts
index d0ea8080c..33ca76fca 100644
--- a/src/web/reconnect.ts
+++ b/src/web/reconnect.ts
@@ -1,6 +1,6 @@
import { randomUUID } from "node:crypto";
-import type { WarelayConfig } from "../config/config.js";
+import type { ClawdisConfig } from "../config/config.js";
export type ReconnectPolicy = {
initialMs: number;
@@ -23,7 +23,7 @@ const clamp = (val: number, min: number, max: number) =>
Math.max(min, Math.min(max, val));
export function resolveHeartbeatSeconds(
- cfg: WarelayConfig,
+ cfg: ClawdisConfig,
overrideSeconds?: number,
): number {
const candidate = overrideSeconds ?? cfg.web?.heartbeatSeconds;
@@ -32,7 +32,7 @@ export function resolveHeartbeatSeconds(
}
export function resolveReconnectPolicy(
- cfg: WarelayConfig,
+ cfg: ClawdisConfig,
overrides?: Partial,
): ReconnectPolicy {
const merged = {