clawmoney 0.17.22 → 0.17.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -102,7 +102,21 @@ export class WsClient {
102
102
  this.stopHeartbeat();
103
103
  this.heartbeatTimer = setInterval(() => {
104
104
  if (this.ws && this.ws.readyState === WebSocket.OPEN) {
105
- this.ws.ping();
105
+ // Application-level heartbeat. Backend's `event == "heartbeat"`
106
+ // handler is what updates ClawAgent.last_heartbeat_at, which in
107
+ // turn drives the `agent_is_online` field on /market/skills/search
108
+ // results. A WS protocol-level ping/pong (this.ws.ping()) keeps
109
+ // the TCP connection alive but the backend never sees it as a
110
+ // JSON message — so DB heartbeat would only ever get bumped at
111
+ // initial connect, then go stale after 600s and the agent would
112
+ // disappear from search results despite the daemon being fine.
113
+ try {
114
+ this.ws.send(JSON.stringify({ event: "heartbeat" }));
115
+ }
116
+ catch {
117
+ // Send failure is non-fatal; the reconnect loop will pick up
118
+ // a real socket close if the connection is actually dead.
119
+ }
106
120
  }
107
121
  }, HEARTBEAT_INTERVAL_MS);
108
122
  this.heartbeatTimer.unref();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clawmoney",
3
- "version": "0.17.22",
3
+ "version": "0.17.24",
4
4
  "description": "ClawMoney CLI -- Earn rewards with your AI agent",
5
5
  "type": "module",
6
6
  "bin": {
@@ -0,0 +1,205 @@
1
+ #!/usr/bin/env bash
2
+ # Install the ClawMoney Market Provider daemon as a launchd user agent on macOS.
3
+ #
4
+ # Why: providers who registered Market skills need their daemon running 7x24
5
+ # so buyer calls (via web chat / market call / etc) actually reach them.
6
+ # Without this script, `clawmoney market start` is a detached one-shot
7
+ # process — fine until the user reboots, closes their laptop, or the
8
+ # daemon crashes overnight.
9
+ #
10
+ # This script generates ~/Library/LaunchAgents/ai.clawmoney.market.plist
11
+ # pointing at the absolute path of the clawmoney binary, then loads it.
12
+ # After running once:
13
+ # - Daemon auto-starts when the user logs into GUI
14
+ # - Daemon auto-restarts if it crashes (with 10s throttle)
15
+ # - WebSocket reconnects to api.bnbot.ai automatically (logic inside
16
+ # the daemon itself; launchd just keeps the host process alive)
17
+ #
18
+ # Usage:
19
+ # ./scripts/install-market-launchd.sh # install + start (default: cli=openclaw)
20
+ # ./scripts/install-market-launchd.sh --cli codex # install + start with codex backend
21
+ # ./scripts/install-market-launchd.sh --cli claude --auto-accept
22
+ # # codex/claude + auto-accept escrow gigs
23
+ # ./scripts/install-market-launchd.sh uninstall # unload + remove plist
24
+ #
25
+ # Pre-reqs:
26
+ # - `clawmoney setup` has written ~/.clawmoney/config.yaml
27
+ # - Provider role registered: `clawmoney market setup` (or `register`)
28
+ # - Whatever underlying CLI you pass via --cli must work standalone first:
29
+ # e.g. `codex --version`, `claude --version`, `openclaw --version`
30
+ # - clawmoney installed globally: npm i -g clawmoney
31
+
32
+ set -euo pipefail
33
+
34
+ LABEL="ai.clawmoney.market"
35
+ PLIST_PATH="$HOME/Library/LaunchAgents/$LABEL.plist"
36
+ LOG_DIR="$HOME/.clawmoney"
37
+ STDOUT_LOG="$LOG_DIR/market.launchd.out.log"
38
+ STDERR_LOG="$LOG_DIR/market.launchd.err.log"
39
+
40
+ if [[ "$(uname)" != "Darwin" ]]; then
41
+ echo "error: this script is for macOS only (launchd)" >&2
42
+ exit 1
43
+ fi
44
+
45
+ if [[ "${1:-}" == "uninstall" ]]; then
46
+ echo "Unloading $LABEL..."
47
+ launchctl bootout "gui/$(id -u)/$LABEL" 2>/dev/null || true
48
+ rm -f "$PLIST_PATH"
49
+ echo "Removed $PLIST_PATH."
50
+ exit 0
51
+ fi
52
+
53
+ # ── Parse args: --cli <backend> [--auto-accept] ───────────────────────────
54
+ CLI=""
55
+ AUTO_ACCEPT=""
56
+ while [[ $# -gt 0 ]]; do
57
+ case "$1" in
58
+ --cli)
59
+ CLI="$2"
60
+ shift 2
61
+ ;;
62
+ --auto-accept)
63
+ AUTO_ACCEPT="--auto-accept"
64
+ shift
65
+ ;;
66
+ -h|--help)
67
+ sed -n '2,30p' "$0"
68
+ exit 0
69
+ ;;
70
+ *)
71
+ echo "error: unknown arg '$1'. Run with -h for usage." >&2
72
+ exit 1
73
+ ;;
74
+ esac
75
+ done
76
+
77
+ CLAWMONEY_BIN="$(command -v clawmoney || true)"
78
+ if [[ -z "$CLAWMONEY_BIN" ]]; then
79
+ echo "error: clawmoney not found in PATH. Install with: npm i -g clawmoney" >&2
80
+ exit 1
81
+ fi
82
+
83
+ # launchd executes with a minimal PATH, so we resolve node + the underlying
84
+ # CLI binary (codex / claude / etc) here and pass their dirs through
85
+ # EnvironmentVariables. The clawmoney binary itself is a Node shebang;
86
+ # its `market start` spawns the configured CLI as a child process, so the
87
+ # child needs to be on PATH at run time.
88
+ NODE_BIN="$(command -v node || true)"
89
+ if [[ -z "$NODE_BIN" ]]; then
90
+ echo "error: node not found in PATH" >&2
91
+ exit 1
92
+ fi
93
+ NODE_DIR="$(dirname "$NODE_BIN")"
94
+
95
+ # If the user passed --cli, sanity-check it exists.
96
+ CLI_DIR=""
97
+ if [[ -n "$CLI" ]]; then
98
+ CLI_BIN="$(command -v "$CLI" || true)"
99
+ if [[ -z "$CLI_BIN" ]]; then
100
+ echo "warning: '$CLI' not found in PATH. Daemon will spawn it and may fail." >&2
101
+ else
102
+ CLI_DIR="$(dirname "$CLI_BIN")"
103
+ fi
104
+ fi
105
+
106
+ mkdir -p "$LOG_DIR"
107
+ mkdir -p "$(dirname "$PLIST_PATH")"
108
+
109
+ # Build the ProgramArguments array dynamically based on flags.
110
+ PROGRAM_ARGS=" <string>$CLAWMONEY_BIN</string>
111
+ <string>market</string>
112
+ <string>start</string>"
113
+ if [[ -n "$CLI" ]]; then
114
+ PROGRAM_ARGS+="
115
+ <string>--cli</string>
116
+ <string>$CLI</string>"
117
+ fi
118
+ if [[ -n "$AUTO_ACCEPT" ]]; then
119
+ PROGRAM_ARGS+="
120
+ <string>$AUTO_ACCEPT</string>"
121
+ fi
122
+
123
+ # Build a PATH that includes node + the CLI binary's dir + common locations.
124
+ RUN_PATH="$NODE_DIR"
125
+ if [[ -n "$CLI_DIR" && "$CLI_DIR" != "$NODE_DIR" ]]; then
126
+ RUN_PATH="$RUN_PATH:$CLI_DIR"
127
+ fi
128
+ RUN_PATH="$RUN_PATH:/usr/local/bin:/opt/homebrew/bin:/usr/bin:/bin"
129
+
130
+ cat > "$PLIST_PATH" <<EOF
131
+ <?xml version="1.0" encoding="UTF-8"?>
132
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
133
+ <plist version="1.0">
134
+ <dict>
135
+ <key>Label</key>
136
+ <string>$LABEL</string>
137
+
138
+ <key>ProgramArguments</key>
139
+ <array>
140
+ $PROGRAM_ARGS
141
+ </array>
142
+
143
+ <key>RunAtLoad</key>
144
+ <true/>
145
+
146
+ <key>KeepAlive</key>
147
+ <true/>
148
+
149
+ <!-- Restart no more than once per 10 seconds if it crashes in a loop. -->
150
+ <key>ThrottleInterval</key>
151
+ <integer>10</integer>
152
+
153
+ <!-- Interactive: run inside the user's GUI login session so any CLI
154
+ that needs the Keychain (codex with ChatGPT OAuth, claude with
155
+ its own OAuth) can read its tokens. -->
156
+ <key>ProcessType</key>
157
+ <string>Interactive</string>
158
+
159
+ <key>EnvironmentVariables</key>
160
+ <dict>
161
+ <key>PATH</key>
162
+ <string>$RUN_PATH</string>
163
+ <key>HOME</key>
164
+ <string>$HOME</string>
165
+ </dict>
166
+
167
+ <key>WorkingDirectory</key>
168
+ <string>$HOME</string>
169
+
170
+ <key>StandardOutPath</key>
171
+ <string>$STDOUT_LOG</string>
172
+ <key>StandardErrorPath</key>
173
+ <string>$STDERR_LOG</string>
174
+ </dict>
175
+ </plist>
176
+ EOF
177
+
178
+ chmod 0644 "$PLIST_PATH"
179
+
180
+ echo "Wrote $PLIST_PATH."
181
+
182
+ # Stop the foreground daemon (if any) before launchd takes over — otherwise
183
+ # both processes try to claim the same WebSocket slot and the second one
184
+ # loses (or worse, they fight over orders).
185
+ EXISTING_PID="$("$CLAWMONEY_BIN" market status 2>/dev/null | sed -nE 's/.*PID ([0-9]+).*/\1/p' | head -1 || true)"
186
+ if [[ -n "$EXISTING_PID" ]]; then
187
+ echo "Stopping existing foreground daemon (PID $EXISTING_PID)..."
188
+ "$CLAWMONEY_BIN" market stop >/dev/null 2>&1 || true
189
+ sleep 1
190
+ fi
191
+
192
+ echo "Loading into launchd..."
193
+ launchctl bootout "gui/$(id -u)/$LABEL" 2>/dev/null || true
194
+ launchctl bootstrap "gui/$(id -u)" "$PLIST_PATH"
195
+
196
+ echo ""
197
+ echo "Market Provider is running under launchd."
198
+ echo " Label: $LABEL"
199
+ echo " cli: ${CLI:-(default: openclaw)}"
200
+ echo " auto-accept: ${AUTO_ACCEPT:+yes}${AUTO_ACCEPT:-no}"
201
+ echo " logs: $STDOUT_LOG"
202
+ echo " $STDERR_LOG"
203
+ echo " $LOG_DIR/provider.log (daemon-internal log)"
204
+ echo " status: clawmoney market status"
205
+ echo " uninstall: ./scripts/install-market-launchd.sh uninstall"