troxy-cli 1.6.0 → 1.7.0

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.
package/bin/troxy.js CHANGED
@@ -147,6 +147,13 @@ switch (command) {
147
147
  await runMcp();
148
148
  break;
149
149
 
150
+ // ── Heartbeat daemon (background service) ─────────────────────
151
+ case 'daemon': {
152
+ const { runDaemon } = await import('../src/daemon.js');
153
+ await runDaemon();
154
+ break;
155
+ }
156
+
150
157
  // ── Pause / resume payment evaluations ───────────────────────
151
158
  case 'pause':
152
159
  await runPause();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "troxy-cli",
3
- "version": "1.6.0",
3
+ "version": "1.7.0",
4
4
  "description": "AI payment control — protect your agent's payments with policies",
5
5
  "type": "module",
6
6
  "bin": {
package/src/daemon.js ADDED
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Troxy heartbeat daemon.
3
+ * Runs as a background service (systemd / launchd). Sends a heartbeat to the
4
+ * Troxy API every 60 seconds so the dashboard shows this agent as connected.
5
+ * Does NOT start an MCP stdio server — that only makes sense when an MCP client
6
+ * (Claude Desktop, Cursor, etc.) is present.
7
+ */
8
+ import { loadConfig } from './config.js';
9
+ import * as api from './api.js';
10
+
11
+ const INTERVAL_MS = 60_000;
12
+
13
+ export async function runDaemon() {
14
+ const cfg = loadConfig();
15
+ if (!cfg?.apiKey) {
16
+ process.stderr.write('[troxy-daemon] No API key found. Run troxy init first.\n');
17
+ process.exit(1);
18
+ }
19
+
20
+ const { apiKey, agentName } = cfg;
21
+
22
+ const beat = () =>
23
+ api.mcpHeartbeat(apiKey, agentName)
24
+ .then(() => process.stderr.write(`[troxy-daemon] heartbeat ok\n`))
25
+ .catch(err => process.stderr.write(`[troxy-daemon] heartbeat failed: ${err.message}\n`));
26
+
27
+ process.stderr.write(`[troxy-daemon] starting (agent: ${agentName || 'unnamed'})\n`);
28
+ await beat();
29
+ setInterval(beat, INTERVAL_MS);
30
+
31
+ // Keep process alive indefinitely
32
+ process.stdin.resume();
33
+ }
package/src/init.js CHANGED
@@ -154,7 +154,7 @@ export async function runInit({ key } = {}) {
154
154
  console.log(' Background service installed ✓');
155
155
  } catch (err) {
156
156
  console.log(` Background service ✗ (${err.message})`);
157
- console.log(' You can start it manually with: troxy mcp &');
157
+ console.log(' You can start it manually with: troxy daemon &');
158
158
  }
159
159
 
160
160
  console.log('\n Your payments are now protected.');
@@ -179,7 +179,7 @@ Description=Troxy MCP Server
179
179
  After=network.target
180
180
 
181
181
  [Service]
182
- ExecStart=${troxy} mcp
182
+ ExecStart=${troxy} daemon
183
183
  Restart=always
184
184
  RestartSec=10
185
185
  User=${os.userInfo().username}
@@ -205,7 +205,7 @@ WantedBy=multi-user.target
205
205
  <key>ProgramArguments</key>
206
206
  <array>
207
207
  <string>${troxy}</string>
208
- <string>mcp</string>
208
+ <string>daemon</string>
209
209
  </array>
210
210
  <key>EnvironmentVariables</key>
211
211
  <dict>