clawmoney 0.17.43 → 0.17.45

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.
@@ -1,5 +1,4 @@
1
1
  import { spawn } from "node:child_process";
2
- import { openSync, closeSync } from "node:fs";
3
2
  import { join } from "node:path";
4
3
  import { homedir } from "node:os";
5
4
  import chalk from "chalk";
@@ -19,11 +18,12 @@ export async function taskStartCommand() {
19
18
  const thisDir = import.meta.url.replace("file://", "").replace(/\/[^/]+$/, "");
20
19
  const parentDir = thisDir.replace(/\/[^/]+$/, "");
21
20
  const daemonScript = join(parentDir, "task", "daemon.js");
22
- // Open log file for stdout/stderr capture (daemon detaches from parent).
23
- const out = openSync(LOG_FILE, "a");
24
- const err = openSync(LOG_FILE, "a");
21
+ // Daemon writes its own log file via console.log redirect. Parent
22
+ // uses stdio:"ignore" so it doesn't keep any fd open — that lets the
23
+ // parent process exit cleanly after spawn, which is the only way
24
+ // desktop's ensure_task_daemon_running can poll for a live PID.
25
25
  const child = spawn(process.execPath, [daemonScript], {
26
- stdio: ["ignore", out, err],
26
+ stdio: "ignore",
27
27
  detached: true,
28
28
  env: {
29
29
  ...process.env,
@@ -35,11 +35,6 @@ export async function taskStartCommand() {
35
35
  },
36
36
  });
37
37
  child.unref();
38
- // Release fds in the parent — keeping them open keeps node's event
39
- // loop alive (the parent never exits), and stale parent processes
40
- // mean each desktop dashboard refresh would re-spawn another daemon.
41
- closeSync(out);
42
- closeSync(err);
43
38
  await new Promise((r) => setTimeout(r, 1000));
44
39
  const pid = readTaskPid();
45
40
  if (pid && isPidAlive(pid)) {
@@ -20,10 +20,32 @@
20
20
  * No CLI integration yet — that lands in Phase 3 alongside the proper
21
21
  * `clawmoney task start` command.
22
22
  */
23
- import { readFileSync, writeFileSync, unlinkSync, existsSync } from "node:fs";
23
+ import { readFileSync, writeFileSync, unlinkSync, existsSync, appendFileSync, mkdirSync } from "node:fs";
24
24
  import { join } from "node:path";
25
25
  import { homedir } from "node:os";
26
+ import { fileURLToPath } from "node:url";
26
27
  import YAML from "yaml";
28
+ const TASK_LOG_FILE = join(homedir(), ".clawmoney", "task.log");
29
+ function tsLine(level, msg) {
30
+ const ts = new Date().toISOString().replace("T", " ").replace("Z", "");
31
+ return `${ts} [${level}] ${msg}\n`;
32
+ }
33
+ function logToFile(level, ...args) {
34
+ const msg = args.map((a) => (typeof a === "string" ? a : JSON.stringify(a))).join(" ");
35
+ const line = tsLine(level, msg);
36
+ try {
37
+ mkdirSync(join(homedir(), ".clawmoney"), { recursive: true });
38
+ appendFileSync(TASK_LOG_FILE, line, "utf-8");
39
+ }
40
+ catch {
41
+ /* best effort */
42
+ }
43
+ }
44
+ function installFileLogger() {
45
+ console.log = (...args) => logToFile("INFO", ...args);
46
+ console.warn = (...args) => logToFile("WARN", ...args);
47
+ console.error = (...args) => logToFile("ERROR", ...args);
48
+ }
27
49
  import { TaskWsClient } from "./ws-client.js";
28
50
  import { getSkill, listSkills } from "./skills/index.js";
29
51
  const CONFIG_DIR = join(homedir(), ".clawmoney");
@@ -165,6 +187,9 @@ async function handleTaskRequest(ws, req) {
165
187
  }
166
188
  }
167
189
  function main() {
190
+ // Daemon was started as a script (stdio:"ignore"); from here on, all
191
+ // log lines should land in ~/.clawmoney/task.log.
192
+ installFileLogger();
168
193
  const existing = readTaskPid();
169
194
  if (existing !== null && isPidAlive(existing)) {
170
195
  console.error(`[task] already running (PID ${existing})`);
@@ -222,4 +247,9 @@ function main() {
222
247
  process.on("SIGTERM", () => shutdown("SIGTERM"));
223
248
  ws.start();
224
249
  }
225
- main();
250
+ // Only run main() when invoked as a script (`node daemon.js`), not when
251
+ // the module is imported (e.g. by src/commands/task.ts which only wants
252
+ // to use readTaskPid / isPidAlive helpers).
253
+ if (process.argv[1] === fileURLToPath(import.meta.url)) {
254
+ main();
255
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clawmoney",
3
- "version": "0.17.43",
3
+ "version": "0.17.45",
4
4
  "description": "ClawMoney CLI -- Earn rewards with your AI agent",
5
5
  "type": "module",
6
6
  "bin": {