clawmoney 0.17.43 → 0.17.44

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,31 @@
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
26
  import YAML from "yaml";
27
+ const TASK_LOG_FILE = join(homedir(), ".clawmoney", "task.log");
28
+ function tsLine(level, msg) {
29
+ const ts = new Date().toISOString().replace("T", " ").replace("Z", "");
30
+ return `${ts} [${level}] ${msg}\n`;
31
+ }
32
+ function logToFile(level, ...args) {
33
+ const msg = args.map((a) => (typeof a === "string" ? a : JSON.stringify(a))).join(" ");
34
+ const line = tsLine(level, msg);
35
+ try {
36
+ mkdirSync(join(homedir(), ".clawmoney"), { recursive: true });
37
+ appendFileSync(TASK_LOG_FILE, line, "utf-8");
38
+ }
39
+ catch {
40
+ /* best effort */
41
+ }
42
+ }
43
+ // Redirect console.* to the file so daemon log lines persist even when
44
+ // the daemon is spawned with stdio:"ignore" by `clawmoney task start`.
45
+ console.log = (...args) => logToFile("INFO", ...args);
46
+ console.warn = (...args) => logToFile("WARN", ...args);
47
+ console.error = (...args) => logToFile("ERROR", ...args);
27
48
  import { TaskWsClient } from "./ws-client.js";
28
49
  import { getSkill, listSkills } from "./skills/index.js";
29
50
  const CONFIG_DIR = join(homedir(), ".clawmoney");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clawmoney",
3
- "version": "0.17.43",
3
+ "version": "0.17.44",
4
4
  "description": "ClawMoney CLI -- Earn rewards with your AI agent",
5
5
  "type": "module",
6
6
  "bin": {