@mclawnet/agent 0.6.18 → 0.6.20

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/cli.js CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  import { Command } from "commander";
4
4
  import { readFileSync } from "fs";
5
+ import { hostname } from "os";
6
+ import { createInterface } from "readline";
5
7
 
6
8
  const pkg = JSON.parse(readFileSync(new URL("./package.json", import.meta.url), "utf-8"));
7
9
 
@@ -12,6 +14,74 @@ program
12
14
  .description("ClawNet Agent — intelligent agent daemon service")
13
15
  .version(pkg.version);
14
16
 
17
+ // --- helpers ---
18
+ function prompt(question) {
19
+ const rl = createInterface({ input: process.stdin, output: process.stdout });
20
+ return new Promise((resolve) => rl.question(question, (ans) => { rl.close(); resolve(ans); }));
21
+ }
22
+
23
+ function validateToken(t) {
24
+ if (!t) return "Token is required.";
25
+ if (!t.startsWith("clw_")) return "Token must start with 'clw_'.";
26
+ if (t.length < 24) return "Token looks too short.";
27
+ return null;
28
+ }
29
+
30
+ function printNeedsInit() {
31
+ process.stderr.write(
32
+ "\n✗ Agent not configured.\n\n" +
33
+ " Token is missing. Run:\n\n" +
34
+ " clawnet-agent init\n\n" +
35
+ " Get your token from https://mclaw.work/settings → Security\n\n"
36
+ );
37
+ }
38
+
39
+ // === init ===
40
+ program
41
+ .command("init")
42
+ .description("Initialize ~/.clawnet/settings.json (token + name)")
43
+ .option("--token <token>", "Agent token (skip interactive prompt)")
44
+ .option("--name <name>", "Agent name (skip interactive prompt)")
45
+ .option("--hub-url <url>", "Hub WebSocket URL (defaults to wss://mclaw.work/ws/agent)")
46
+ .action(async (opts) => {
47
+ const { saveConfig, loadConfig } = await import("./dist/index.js");
48
+
49
+ const existing = loadConfig();
50
+
51
+ let token = opts.token;
52
+ if (!token) {
53
+ while (true) {
54
+ const ans = (await prompt("Token (from https://mclaw.work/settings → Security): ")).trim();
55
+ const err = validateToken(ans);
56
+ if (err) {
57
+ process.stderr.write(` ${err}\n`);
58
+ continue;
59
+ }
60
+ token = ans;
61
+ break;
62
+ }
63
+ } else {
64
+ const err = validateToken(token);
65
+ if (err) {
66
+ console.error(`[clawnet] ${err}`);
67
+ process.exit(1);
68
+ }
69
+ }
70
+
71
+ let name = opts.name;
72
+ if (!name) {
73
+ const def = existing.name || hostname();
74
+ const ans = (await prompt(`Agent name [${def}]: `)).trim();
75
+ name = ans || def;
76
+ }
77
+
78
+ const hubUrl = opts.hubUrl || existing.hubUrl || "wss://mclaw.work/ws/agent";
79
+
80
+ saveConfig({ token, name, hubUrl, backendType: "claude-code" });
81
+ console.log("\n✓ Saved to ~/.clawnet/settings.json");
82
+ console.log(" Run 'clawnet-agent start' to start the agent.\n");
83
+ });
84
+
15
85
  // === start (default command) ===
16
86
  program
17
87
  .command("start", { isDefault: true })
@@ -24,12 +94,20 @@ program
24
94
  .action(async (opts) => {
25
95
  if (opts.foreground) {
26
96
  // Foreground mode: directly run agent (existing behavior)
97
+ const { loadConfig } = await import("./dist/index.js");
98
+ const fileConfig = loadConfig();
27
99
  const config = {};
28
100
  if (opts.hubUrl) config.hubUrl = opts.hubUrl;
29
101
  if (opts.token) config.token = opts.token;
30
102
  if (opts.name) config.name = opts.name;
31
103
  if (opts.backend) config.backendType = opts.backend;
32
104
 
105
+ const effectiveToken = config.token || fileConfig.token;
106
+ if (!effectiveToken) {
107
+ printNeedsInit();
108
+ process.exit(1);
109
+ }
110
+
33
111
  let adapter;
34
112
  const backendType = opts.backend || "claude-code";
35
113
  if (backendType === "claude-code") {
@@ -58,7 +136,15 @@ program
58
136
  if (opts.name) cliOpts.name = opts.name;
59
137
 
60
138
  const config = mergeServiceConfig(cliOpts);
61
- validateServiceConfig(config);
139
+ try {
140
+ validateServiceConfig(config);
141
+ } catch (err) {
142
+ if (/token/i.test(err.message)) {
143
+ printNeedsInit();
144
+ process.exit(1);
145
+ }
146
+ throw err;
147
+ }
62
148
  saveServiceConfig(config);
63
149
 
64
150
  const manager = await getServiceManager();
@@ -175,6 +261,89 @@ configCmd
175
261
  console.log(`Set ${key} = ${value}`);
176
262
  });
177
263
 
264
+ const CONFIG_SCHEMA = [
265
+ {
266
+ key: "hubUrl",
267
+ description: "Hub WebSocket URL the agent connects to.",
268
+ default: "wss://mclaw.work/ws/agent",
269
+ },
270
+ {
271
+ key: "token",
272
+ description: "Agent auth token. Generate at https://mclaw.work/settings → Security.",
273
+ default: "(required, no default)",
274
+ secret: true,
275
+ },
276
+ {
277
+ key: "name",
278
+ description: "Display name for this agent in the hub.",
279
+ default: "<os.hostname()>",
280
+ },
281
+ {
282
+ key: "backendType",
283
+ description: "LLM backend implementation. Currently only 'claude-code' is supported.",
284
+ default: "claude-code",
285
+ },
286
+ {
287
+ key: "embedding.provider",
288
+ description: "Embedding provider for semantic memory: auto | openai | ollama | hash.",
289
+ default: "auto (falls back to hash if no provider reachable)",
290
+ },
291
+ {
292
+ key: "embedding.openaiBaseUrl",
293
+ description: "OpenAI-compatible API base URL (e.g. http://localhost:4141/v1 for copilot proxy).",
294
+ default: "(unset)",
295
+ },
296
+ {
297
+ key: "embedding.openaiApiKey",
298
+ description: "OpenAI API key (use 'dummy' for copilot proxy).",
299
+ default: "(unset)",
300
+ secret: true,
301
+ },
302
+ {
303
+ key: "embedding.openaiModel",
304
+ description: "OpenAI embedding model name.",
305
+ default: "text-embedding-3-small",
306
+ },
307
+ {
308
+ key: "embedding.ollamaUrl",
309
+ description: "Ollama server URL.",
310
+ default: "http://localhost:11434",
311
+ },
312
+ {
313
+ key: "embedding.ollamaModel",
314
+ description: "Ollama embedding model name.",
315
+ default: "nomic-embed-text",
316
+ },
317
+ ];
318
+
319
+ function getByPath(obj, path) {
320
+ return path.split(".").reduce((o, k) => (o == null ? undefined : o[k]), obj);
321
+ }
322
+
323
+ function maskValue(v) {
324
+ if (typeof v !== "string") return v;
325
+ if (v.length <= 8) return "•".repeat(v.length);
326
+ return v.slice(0, 4) + "…" + "•".repeat(8);
327
+ }
328
+
329
+ configCmd
330
+ .command("list")
331
+ .description("List all configurable fields with descriptions and current values")
332
+ .action(async () => {
333
+ const { loadConfig } = await import("./dist/index.js");
334
+ const cfg = loadConfig();
335
+ console.log("ClawNet Agent configuration (~/.clawnet/settings.json)\n");
336
+ for (const entry of CONFIG_SCHEMA) {
337
+ const cur = getByPath(cfg, entry.key);
338
+ const display = cur === undefined ? "(unset)" : entry.secret ? maskValue(cur) : JSON.stringify(cur);
339
+ console.log(` ${entry.key}`);
340
+ console.log(` ${entry.description}`);
341
+ console.log(` default : ${entry.default}`);
342
+ console.log(` current : ${display}\n`);
343
+ }
344
+ console.log("Edit via 'clawnet-agent config set <key> <value>' or by editing ~/.clawnet/settings.json directly.");
345
+ });
346
+
178
347
  program.parseAsync(process.argv).catch((err) => {
179
348
  console.error("[clawnet] Fatal:", err.message || err);
180
349
  process.exit(1);
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  loadConfig,
3
3
  saveConfig
4
- } from "./chunk-CBZIH6FY.js";
4
+ } from "./chunk-PJ5M6Q36.js";
5
5
 
6
6
  // src/service/config.ts
7
7
  import { existsSync, readFileSync } from "fs";
@@ -85,4 +85,4 @@ export {
85
85
  validateServiceConfig,
86
86
  mergeServiceConfig
87
87
  };
88
- //# sourceMappingURL=chunk-RO47ET27.js.map
88
+ //# sourceMappingURL=chunk-M2CDVPQF.js.map
@@ -6,7 +6,7 @@ import { createLogger } from "@mclawnet/logger";
6
6
  var log = createLogger({ module: "config" });
7
7
  var CONFIG_DIR = join(homedir(), ".clawnet");
8
8
  var SETTINGS_FILE = join(CONFIG_DIR, "settings.json");
9
- var DEFAULT_HUB_URL = process.env.CLAWNET_DEFAULT_HUB_URL || "ws://localhost:3000/ws/agent";
9
+ var DEFAULT_HUB_URL = process.env.CLAWNET_DEFAULT_HUB_URL || "wss://mclaw.work/ws/agent";
10
10
  var DEFAULTS = {
11
11
  hubUrl: DEFAULT_HUB_URL,
12
12
  token: "",
@@ -90,4 +90,4 @@ export {
90
90
  loadConfig,
91
91
  saveConfig
92
92
  };
93
- //# sourceMappingURL=chunk-CBZIH6FY.js.map
93
+ //# sourceMappingURL=chunk-PJ5M6Q36.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/config.ts"],"sourcesContent":["import { readFileSync, writeFileSync, mkdirSync, existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { homedir, hostname } from \"node:os\";\nimport type { BackendType } from \"@mclawnet/shared\";\nimport { createLogger } from \"@mclawnet/logger\";\n\nconst log = createLogger({ module: \"config\" });\n\nexport interface EmbeddingConfig {\n /** Embedding provider mode: auto / openai / ollama / hash */\n provider?: string;\n /** OpenAI-compatible API base URL (e.g. http://localhost:4141/v1 for copilot proxy) */\n openaiBaseUrl?: string;\n /** OpenAI API key (use \"dummy\" for copilot proxy) */\n openaiApiKey?: string;\n /** OpenAI embedding model name */\n openaiModel?: string;\n /** Ollama server URL */\n ollamaUrl?: string;\n /** Ollama embedding model name */\n ollamaModel?: string;\n}\n\nexport interface AgentConfig {\n hubUrl: string;\n token: string;\n name: string;\n backendType: BackendType;\n embedding?: EmbeddingConfig;\n}\n\nconst CONFIG_DIR = join(homedir(), \".clawnet\");\nconst SETTINGS_FILE = join(CONFIG_DIR, \"settings.json\");\n\nconst DEFAULT_HUB_URL = process.env.CLAWNET_DEFAULT_HUB_URL || \"wss://mclaw.work/ws/agent\";\n\nconst DEFAULTS: AgentConfig = {\n hubUrl: DEFAULT_HUB_URL,\n token: \"\",\n name: hostname(),\n backendType: \"claude-code\",\n};\n\n/** Ensure hubUrl uses ws(s):// protocol and ends with /ws/agent */\nfunction normalizeHubUrl(url: string): string {\n // Convert http(s):// to ws(s)://\n url = url.replace(/^https:\\/\\//, \"wss://\").replace(/^http:\\/\\//, \"ws://\");\n // Default to wss:// if no protocol\n if (!/^wss?:\\/\\//.test(url)) url = \"wss://\" + url;\n if (url.endsWith(\"/ws/agent\")) return url;\n return url.replace(/\\/+$/, \"\") + \"/ws/agent\";\n}\n\n/**\n * Map structured embedding config to CLAWNET_* env vars.\n * Only sets vars that are not already defined in process.env.\n */\nfunction applyEmbeddingConfig(embedding: EmbeddingConfig): void {\n const mapping: Array<[keyof EmbeddingConfig, string]> = [\n [\"provider\", \"CLAWNET_EMBEDDING_PROVIDER\"],\n [\"openaiBaseUrl\", \"CLAWNET_OPENAI_BASE_URL\"],\n [\"openaiApiKey\", \"CLAWNET_OPENAI_API_KEY\"],\n [\"openaiModel\", \"CLAWNET_OPENAI_EMBEDDING_MODEL\"],\n [\"ollamaUrl\", \"CLAWNET_OLLAMA_URL\"],\n [\"ollamaModel\", \"CLAWNET_OLLAMA_MODEL\"],\n ];\n\n for (const [configKey, envKey] of mapping) {\n const value = embedding[configKey];\n if (value !== undefined && process.env[envKey] === undefined) {\n process.env[envKey] = value;\n }\n }\n}\n\n/** Load config: CLI opts > env vars > settings file > defaults */\nexport function loadConfig(cliOpts: Partial<AgentConfig> = {}): AgentConfig {\n let fileConfig: Partial<AgentConfig> = {};\n\n log.info({ path: SETTINGS_FILE }, \"loading config\");\n\n if (existsSync(SETTINGS_FILE)) {\n try {\n fileConfig = JSON.parse(readFileSync(SETTINGS_FILE, \"utf-8\"));\n log.info(\n { hubUrl: fileConfig.hubUrl, hasToken: !!fileConfig.token, name: fileConfig.name },\n \"settings.json loaded\"\n );\n } catch (e) {\n log.warn({ err: e }, \"failed to parse settings.json\");\n }\n } else {\n log.warn(\"settings.json not found\");\n }\n\n // Apply structured embedding config to process.env\n if (fileConfig.embedding) {\n applyEmbeddingConfig(fileConfig.embedding);\n }\n\n const hubUrl =\n cliOpts.hubUrl ??\n process.env.CLAWNET_HUB_URL ??\n fileConfig.hubUrl ??\n DEFAULTS.hubUrl;\n\n const resolved = {\n hubUrl: normalizeHubUrl(hubUrl),\n token:\n cliOpts.token ??\n process.env.CLAWNET_TOKEN ??\n fileConfig.token ??\n DEFAULTS.token,\n name:\n cliOpts.name ??\n process.env.CLAWNET_NAME ??\n fileConfig.name ??\n DEFAULTS.name,\n backendType:\n (cliOpts.backendType as BackendType) ??\n (process.env.CLAWNET_BACKEND_TYPE as BackendType) ??\n (fileConfig.backendType as BackendType) ??\n DEFAULTS.backendType,\n embedding: fileConfig.embedding,\n };\n\n log.info(\n {\n hubUrl: resolved.hubUrl,\n hubUrlSource: cliOpts.hubUrl ? \"cli\" : process.env.CLAWNET_HUB_URL ? \"env\" : fileConfig.hubUrl ? \"file\" : \"default\",\n tokenSource: cliOpts.token ? \"cli\" : process.env.CLAWNET_TOKEN ? \"env\" : fileConfig.token ? \"file\" : \"default\",\n hasToken: !!resolved.token,\n },\n \"config resolved\"\n );\n\n return resolved;\n}\n\n/** Save config to ~/.clawnet/settings.json */\nexport function saveConfig(config: Partial<AgentConfig>): void {\n mkdirSync(CONFIG_DIR, { recursive: true });\n\n let existing: Partial<AgentConfig> = {};\n if (existsSync(SETTINGS_FILE)) {\n try {\n existing = JSON.parse(readFileSync(SETTINGS_FILE, \"utf-8\"));\n } catch {\n // ignore\n }\n }\n\n const merged = { ...existing, ...config };\n writeFileSync(SETTINGS_FILE, JSON.stringify(merged, null, 2) + \"\\n\");\n}\n"],"mappings":"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","names":[]}
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  loadConfig
3
- } from "./chunk-CBZIH6FY.js";
3
+ } from "./chunk-PJ5M6Q36.js";
4
4
 
5
5
  // src/start.ts
6
6
  import { homedir as homedir3 } from "os";
@@ -1816,4 +1816,4 @@ export {
1816
1816
  FsBridge,
1817
1817
  startAgent
1818
1818
  };
1819
- //# sourceMappingURL=chunk-MSDIRBXF.js.map
1819
+ //# sourceMappingURL=chunk-RIK7IXSW.js.map
package/dist/index.js CHANGED
@@ -4,11 +4,11 @@ import {
4
4
  HubConnection,
5
5
  SessionManager,
6
6
  startAgent
7
- } from "./chunk-MSDIRBXF.js";
7
+ } from "./chunk-RIK7IXSW.js";
8
8
  import {
9
9
  loadConfig,
10
10
  saveConfig
11
- } from "./chunk-CBZIH6FY.js";
11
+ } from "./chunk-PJ5M6Q36.js";
12
12
 
13
13
  // src/index.ts
14
14
  import {
@@ -4,8 +4,8 @@ import {
4
4
  getLogDir,
5
5
  getNodePath,
6
6
  loadServiceConfig
7
- } from "./chunk-RO47ET27.js";
8
- import "./chunk-CBZIH6FY.js";
7
+ } from "./chunk-M2CDVPQF.js";
8
+ import "./chunk-PJ5M6Q36.js";
9
9
 
10
10
  // src/service/linux.ts
11
11
  import { execSync, spawn } from "child_process";
@@ -173,4 +173,4 @@ export {
173
173
  generateUnit,
174
174
  getUnitPath
175
175
  };
176
- //# sourceMappingURL=linux-6AR7SXHW.js.map
176
+ //# sourceMappingURL=linux-IHA4O633.js.map
@@ -4,8 +4,8 @@ import {
4
4
  getLogDir,
5
5
  getNodePath,
6
6
  loadServiceConfig
7
- } from "./chunk-RO47ET27.js";
8
- import "./chunk-CBZIH6FY.js";
7
+ } from "./chunk-M2CDVPQF.js";
8
+ import "./chunk-PJ5M6Q36.js";
9
9
 
10
10
  // src/service/macos.ts
11
11
  import { execSync, spawn } from "child_process";
@@ -15,6 +15,12 @@ import { homedir } from "os";
15
15
  function getPlistPath() {
16
16
  return join(homedir(), "Library", "LaunchAgents", `${SERVICE_LABEL}.plist`);
17
17
  }
18
+ function getDomainTarget() {
19
+ return `gui/${process.getuid()}`;
20
+ }
21
+ function getServiceTarget() {
22
+ return `${getDomainTarget()}/${SERVICE_LABEL}`;
23
+ }
18
24
  function escapeXml(str) {
19
25
  return str.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&apos;");
20
26
  }
@@ -23,6 +29,11 @@ function generatePlist(config) {
23
29
  const cliPath = getCliPath();
24
30
  const logDir = getLogDir();
25
31
  const envEntries = [];
32
+ const pathEnv = process.env.PATH;
33
+ if (pathEnv) {
34
+ envEntries.push(` <key>PATH</key>
35
+ <string>${escapeXml(pathEnv)}</string>`);
36
+ }
26
37
  if (config.hubUrl) {
27
38
  envEntries.push(` <key>CLAWNET_HUB_URL</key>
28
39
  <string>${escapeXml(config.hubUrl)}</string>`);
@@ -78,7 +89,7 @@ var MacOSServiceManager = class {
78
89
  const launchAgentsDir = join(homedir(), "Library", "LaunchAgents");
79
90
  if (existsSync(plistPath)) {
80
91
  try {
81
- execSync(`launchctl unload "${plistPath}"`, { stdio: "ignore" });
92
+ execSync(`launchctl bootout ${getServiceTarget()}`, { stdio: "ignore" });
82
93
  } catch {
83
94
  }
84
95
  }
@@ -95,7 +106,7 @@ var MacOSServiceManager = class {
95
106
  return;
96
107
  }
97
108
  try {
98
- execSync(`launchctl unload "${plistPath}"`, { stdio: "ignore" });
109
+ execSync(`launchctl bootout ${getServiceTarget()}`, { stdio: "ignore" });
99
110
  } catch {
100
111
  }
101
112
  unlinkSync(plistPath);
@@ -106,7 +117,11 @@ var MacOSServiceManager = class {
106
117
  if (!existsSync(plistPath)) {
107
118
  throw new Error("Service not registered. Run clawnet-agent enable first.");
108
119
  }
109
- execSync(`launchctl load "${plistPath}"`, { stdio: "inherit" });
120
+ try {
121
+ execSync(`launchctl bootstrap ${getDomainTarget()} "${plistPath}"`, { stdio: "ignore" });
122
+ } catch {
123
+ }
124
+ execSync(`launchctl kickstart -k ${getServiceTarget()}`, { stdio: "inherit" });
110
125
  console.log("\u2713 Service started");
111
126
  }
112
127
  async stop() {
@@ -116,15 +131,23 @@ var MacOSServiceManager = class {
116
131
  return;
117
132
  }
118
133
  try {
119
- execSync(`launchctl unload "${plistPath}"`, { stdio: "inherit" });
134
+ execSync(`launchctl bootout ${getServiceTarget()}`, { stdio: "inherit" });
120
135
  console.log("\u2713 Service stopped");
121
136
  } catch {
122
137
  console.log("Service not running");
123
138
  }
124
139
  }
125
140
  async restart() {
126
- await this.stop();
127
- await this.start();
141
+ const plistPath = getPlistPath();
142
+ if (!existsSync(plistPath)) {
143
+ throw new Error("Service not registered. Run clawnet-agent enable first.");
144
+ }
145
+ try {
146
+ execSync(`launchctl bootstrap ${getDomainTarget()} "${plistPath}"`, { stdio: "ignore" });
147
+ } catch {
148
+ }
149
+ execSync(`launchctl kickstart -k ${getServiceTarget()}`, { stdio: "inherit" });
150
+ console.log("\u2713 Service restarted");
128
151
  }
129
152
  async status() {
130
153
  try {
@@ -171,4 +194,4 @@ export {
171
194
  generatePlist,
172
195
  getPlistPath
173
196
  };
174
- //# sourceMappingURL=macos-XVPWIH4C.js.map
197
+ //# sourceMappingURL=macos-G4VK2253.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/service/macos.ts"],"sourcesContent":["import { execSync, spawn } from \"child_process\";\nimport { existsSync, writeFileSync, unlinkSync, mkdirSync, chmodSync } from \"fs\";\nimport { join } from \"path\";\nimport { homedir } from \"os\";\nimport type { ServiceManager, ServiceStatus } from \"./types.js\";\nimport {\n SERVICE_LABEL,\n getLogDir,\n getNodePath,\n getCliPath,\n loadServiceConfig,\n type ServiceConfig,\n} from \"./config.js\";\n\nexport function getPlistPath(): string {\n return join(homedir(), \"Library\", \"LaunchAgents\", `${SERVICE_LABEL}.plist`);\n}\n\nfunction getDomainTarget(): string {\n return `gui/${process.getuid!()}`;\n}\n\nfunction getServiceTarget(): string {\n return `${getDomainTarget()}/${SERVICE_LABEL}`;\n}\n\nfunction escapeXml(str: string): string {\n return str\n .replace(/&/g, \"&amp;\")\n .replace(/</g, \"&lt;\")\n .replace(/>/g, \"&gt;\")\n .replace(/\"/g, \"&quot;\")\n .replace(/'/g, \"&apos;\");\n}\n\nexport function generatePlist(config: ServiceConfig): string {\n const nodePath = getNodePath();\n const cliPath = getCliPath();\n const logDir = getLogDir();\n\n const envEntries: string[] = [];\n // Snapshot the user's interactive shell PATH at registration time.\n // launchd otherwise hands the daemon a minimal PATH (/usr/bin:/bin:/usr/sbin:/sbin),\n // which prevents the claude CLI subprocess from finding git/node/etc.\n const pathEnv = process.env.PATH;\n if (pathEnv) {\n envEntries.push(` <key>PATH</key>\\n <string>${escapeXml(pathEnv)}</string>`);\n }\n if (config.hubUrl) {\n envEntries.push(` <key>CLAWNET_HUB_URL</key>\\n <string>${escapeXml(config.hubUrl)}</string>`);\n }\n if (config.token) {\n envEntries.push(` <key>CLAWNET_TOKEN</key>\\n <string>${escapeXml(config.token)}</string>`);\n }\n if (config.name) {\n envEntries.push(` <key>CLAWNET_NAME</key>\\n <string>${escapeXml(config.name)}</string>`);\n }\n\n return `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n <key>Label</key>\n <string>${SERVICE_LABEL}</string>\n <key>ProgramArguments</key>\n <array>\n <string>${nodePath}</string>\n <string>${cliPath}</string>\n <string>start</string>\n <string>-f</string>\n </array>\n <key>WorkingDirectory</key>\n <string>${homedir()}</string>\n <key>EnvironmentVariables</key>\n <dict>\n${envEntries.join(\"\\n\")}\n </dict>\n <key>RunAtLoad</key>\n <true/>\n <key>KeepAlive</key>\n <dict>\n <key>SuccessfulExit</key>\n <false/>\n </dict>\n <key>ThrottleInterval</key>\n <integer>10</integer>\n <key>StandardOutPath</key>\n <string>${logDir}/out.log</string>\n <key>StandardErrorPath</key>\n <string>${logDir}/error.log</string>\n</dict>\n</plist>`;\n}\n\nexport class MacOSServiceManager implements ServiceManager {\n async install(): Promise<void> {\n const config = loadServiceConfig();\n const plistPath = getPlistPath();\n const logDir = getLogDir();\n const launchAgentsDir = join(homedir(), \"Library\", \"LaunchAgents\");\n\n if (existsSync(plistPath)) {\n try {\n execSync(`launchctl bootout ${getServiceTarget()}`, { stdio: \"ignore\" });\n } catch { /* not loaded */ }\n }\n\n if (!existsSync(launchAgentsDir)) mkdirSync(launchAgentsDir, { recursive: true });\n if (!existsSync(logDir)) mkdirSync(logDir, { recursive: true });\n\n writeFileSync(plistPath, generatePlist(config), \"utf-8\");\n chmodSync(plistPath, 0o600);\n console.log(`✓ Service registered: ${plistPath}`);\n }\n\n async uninstall(): Promise<void> {\n const plistPath = getPlistPath();\n if (!existsSync(plistPath)) {\n console.log(\"Service not registered\");\n return;\n }\n try {\n execSync(`launchctl bootout ${getServiceTarget()}`, { stdio: \"ignore\" });\n } catch { /* not loaded */ }\n unlinkSync(plistPath);\n console.log(\"✓ Service removed\");\n }\n\n async start(): Promise<void> {\n const plistPath = getPlistPath();\n if (!existsSync(plistPath)) {\n throw new Error(\"Service not registered. Run clawnet-agent enable first.\");\n }\n try {\n execSync(`launchctl bootstrap ${getDomainTarget()} \"${plistPath}\"`, { stdio: \"ignore\" });\n } catch { /* already bootstrapped */ }\n execSync(`launchctl kickstart -k ${getServiceTarget()}`, { stdio: \"inherit\" });\n console.log(\"✓ Service started\");\n }\n\n async stop(): Promise<void> {\n const plistPath = getPlistPath();\n if (!existsSync(plistPath)) {\n console.log(\"Service not registered\");\n return;\n }\n try {\n execSync(`launchctl bootout ${getServiceTarget()}`, { stdio: \"inherit\" });\n console.log(\"✓ Service stopped\");\n } catch {\n console.log(\"Service not running\");\n }\n }\n\n async restart(): Promise<void> {\n const plistPath = getPlistPath();\n if (!existsSync(plistPath)) {\n throw new Error(\"Service not registered. Run clawnet-agent enable first.\");\n }\n try {\n execSync(`launchctl bootstrap ${getDomainTarget()} \"${plistPath}\"`, { stdio: \"ignore\" });\n } catch { /* already bootstrapped */ }\n execSync(`launchctl kickstart -k ${getServiceTarget()}`, { stdio: \"inherit\" });\n console.log(\"✓ Service restarted\");\n }\n\n async status(): Promise<ServiceStatus> {\n try {\n const output = execSync(\n `launchctl list | grep ${SERVICE_LABEL}`,\n { encoding: \"utf-8\" }\n ).trim();\n if (!output) return { running: false };\n const [pidStr, exitCodeStr] = output.split(/\\s+/);\n const pid = pidStr === \"-\" ? undefined : parseInt(pidStr, 10);\n const exitCode = parseInt(exitCodeStr, 10);\n return { running: pid !== undefined, pid, exitCode };\n } catch {\n return { running: false };\n }\n }\n\n async printStatus(): Promise<void> {\n const s = await this.status();\n console.log(\"ClawNet Agent\");\n console.log(` Status: ${s.running ? \"Running ✓\" : \"Stopped ✗\"}`);\n if (s.pid) console.log(` PID: ${s.pid}`);\n if (s.exitCode !== undefined && !s.running) console.log(` Exit code: ${s.exitCode}`);\n console.log(\" Platform: macOS (launchd)\");\n }\n\n async logs(options: { follow?: boolean; lines?: number } = {}): Promise<void> {\n const logDir = getLogDir();\n const outLog = join(logDir, \"out.log\");\n const errLog = join(logDir, \"error.log\");\n\n const files: string[] = [];\n if (existsSync(outLog)) files.push(outLog);\n if (existsSync(errLog)) files.push(errLog);\n\n if (files.length === 0) {\n console.log(\"No logs yet\");\n return;\n }\n\n const lines = options.lines || 100;\n const args = options.follow\n ? [\"-f\", \"-n\", String(lines), ...files]\n : [\"-n\", String(lines), ...files];\n\n const child = spawn(\"tail\", args, { stdio: \"inherit\" });\n await new Promise<void>((resolve) => child.on(\"close\", resolve));\n }\n}\n"],"mappings":"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","names":[]}
@@ -9,22 +9,22 @@ import {
9
9
  mergeServiceConfig,
10
10
  saveServiceConfig,
11
11
  validateServiceConfig
12
- } from "../chunk-RO47ET27.js";
13
- import "../chunk-CBZIH6FY.js";
12
+ } from "../chunk-M2CDVPQF.js";
13
+ import "../chunk-PJ5M6Q36.js";
14
14
 
15
15
  // src/service/index.ts
16
16
  async function getServiceManager() {
17
17
  switch (process.platform) {
18
18
  case "darwin": {
19
- const { MacOSServiceManager } = await import("../macos-XVPWIH4C.js");
19
+ const { MacOSServiceManager } = await import("../macos-G4VK2253.js");
20
20
  return new MacOSServiceManager();
21
21
  }
22
22
  case "linux": {
23
- const { LinuxServiceManager } = await import("../linux-6AR7SXHW.js");
23
+ const { LinuxServiceManager } = await import("../linux-IHA4O633.js");
24
24
  return new LinuxServiceManager();
25
25
  }
26
26
  case "win32": {
27
- const { WindowsServiceManager } = await import("../windows-IQNSUMN6.js");
27
+ const { WindowsServiceManager } = await import("../windows-P6U3JLUZ.js");
28
28
  return new WindowsServiceManager();
29
29
  }
30
30
  default:
@@ -1 +1 @@
1
- {"version":3,"file":"macos.d.ts","sourceRoot":"","sources":["../../src/service/macos.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAChE,OAAO,EAML,KAAK,aAAa,EACnB,MAAM,aAAa,CAAC;AAErB,wBAAgB,YAAY,IAAI,MAAM,CAErC;AAWD,wBAAgB,aAAa,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM,CAkD3D;AAED,qBAAa,mBAAoB,YAAW,cAAc;IAClD,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAoBxB,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;IAa1B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAStB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAcrB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAKxB,MAAM,IAAI,OAAO,CAAC,aAAa,CAAC;IAgBhC,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC;IAS5B,IAAI,CAAC,OAAO,GAAE;QAAE,MAAM,CAAC,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAO,GAAG,OAAO,CAAC,IAAI,CAAC;CAsB9E"}
1
+ {"version":3,"file":"macos.d.ts","sourceRoot":"","sources":["../../src/service/macos.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAChE,OAAO,EAML,KAAK,aAAa,EACnB,MAAM,aAAa,CAAC;AAErB,wBAAgB,YAAY,IAAI,MAAM,CAErC;AAmBD,wBAAgB,aAAa,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM,CAyD3D;AAED,qBAAa,mBAAoB,YAAW,cAAc;IAClD,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAoBxB,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;IAa1B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAYtB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAcrB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAYxB,MAAM,IAAI,OAAO,CAAC,aAAa,CAAC;IAgBhC,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC;IAS5B,IAAI,CAAC,OAAO,GAAE;QAAE,MAAM,CAAC,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAO,GAAG,OAAO,CAAC,IAAI,CAAC;CAsB9E"}
package/dist/start.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  startAgent
3
- } from "./chunk-MSDIRBXF.js";
4
- import "./chunk-CBZIH6FY.js";
3
+ } from "./chunk-RIK7IXSW.js";
4
+ import "./chunk-PJ5M6Q36.js";
5
5
  export {
6
6
  startAgent
7
7
  };
@@ -5,8 +5,8 @@ import {
5
5
  getLogDir,
6
6
  getNodePath,
7
7
  loadServiceConfig
8
- } from "./chunk-RO47ET27.js";
9
- import "./chunk-CBZIH6FY.js";
8
+ } from "./chunk-M2CDVPQF.js";
9
+ import "./chunk-PJ5M6Q36.js";
10
10
 
11
11
  // src/service/windows.ts
12
12
  import { execSync, spawn } from "child_process";
@@ -162,4 +162,4 @@ export {
162
162
  generateEcosystem,
163
163
  getEcosystemPath
164
164
  };
165
- //# sourceMappingURL=windows-IQNSUMN6.js.map
165
+ //# sourceMappingURL=windows-P6U3JLUZ.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mclawnet/agent",
3
- "version": "0.6.18",
3
+ "version": "0.6.20",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": {
@@ -22,12 +22,12 @@
22
22
  "dependencies": {
23
23
  "commander": "^14.0.3",
24
24
  "ws": "^8.19.0",
25
- "@mclawnet/shared": "0.1.2",
25
+ "@mclawnet/claude-adapter": "0.1.14",
26
26
  "@mclawnet/logger": "0.1.5",
27
- "@mclawnet/skill-manager": "0.1.3",
28
- "@mclawnet/claude-adapter": "0.1.12",
27
+ "@mclawnet/shared": "0.1.2",
29
28
  "@mclawnet/swarm": "0.1.4",
30
29
  "@mclawnet/mcp-server": "0.1.3",
30
+ "@mclawnet/skill-manager": "0.1.3",
31
31
  "@mclawnet/memory": "0.1.4"
32
32
  },
33
33
  "devDependencies": {
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/config.ts"],"sourcesContent":["import { readFileSync, writeFileSync, mkdirSync, existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { homedir, hostname } from \"node:os\";\nimport type { BackendType } from \"@mclawnet/shared\";\nimport { createLogger } from \"@mclawnet/logger\";\n\nconst log = createLogger({ module: \"config\" });\n\nexport interface EmbeddingConfig {\n /** Embedding provider mode: auto / openai / ollama / hash */\n provider?: string;\n /** OpenAI-compatible API base URL (e.g. http://localhost:4141/v1 for copilot proxy) */\n openaiBaseUrl?: string;\n /** OpenAI API key (use \"dummy\" for copilot proxy) */\n openaiApiKey?: string;\n /** OpenAI embedding model name */\n openaiModel?: string;\n /** Ollama server URL */\n ollamaUrl?: string;\n /** Ollama embedding model name */\n ollamaModel?: string;\n}\n\nexport interface AgentConfig {\n hubUrl: string;\n token: string;\n name: string;\n backendType: BackendType;\n embedding?: EmbeddingConfig;\n}\n\nconst CONFIG_DIR = join(homedir(), \".clawnet\");\nconst SETTINGS_FILE = join(CONFIG_DIR, \"settings.json\");\n\nconst DEFAULT_HUB_URL = process.env.CLAWNET_DEFAULT_HUB_URL || \"ws://localhost:3000/ws/agent\";\n\nconst DEFAULTS: AgentConfig = {\n hubUrl: DEFAULT_HUB_URL,\n token: \"\",\n name: hostname(),\n backendType: \"claude-code\",\n};\n\n/** Ensure hubUrl uses ws(s):// protocol and ends with /ws/agent */\nfunction normalizeHubUrl(url: string): string {\n // Convert http(s):// to ws(s)://\n url = url.replace(/^https:\\/\\//, \"wss://\").replace(/^http:\\/\\//, \"ws://\");\n // Default to wss:// if no protocol\n if (!/^wss?:\\/\\//.test(url)) url = \"wss://\" + url;\n if (url.endsWith(\"/ws/agent\")) return url;\n return url.replace(/\\/+$/, \"\") + \"/ws/agent\";\n}\n\n/**\n * Map structured embedding config to CLAWNET_* env vars.\n * Only sets vars that are not already defined in process.env.\n */\nfunction applyEmbeddingConfig(embedding: EmbeddingConfig): void {\n const mapping: Array<[keyof EmbeddingConfig, string]> = [\n [\"provider\", \"CLAWNET_EMBEDDING_PROVIDER\"],\n [\"openaiBaseUrl\", \"CLAWNET_OPENAI_BASE_URL\"],\n [\"openaiApiKey\", \"CLAWNET_OPENAI_API_KEY\"],\n [\"openaiModel\", \"CLAWNET_OPENAI_EMBEDDING_MODEL\"],\n [\"ollamaUrl\", \"CLAWNET_OLLAMA_URL\"],\n [\"ollamaModel\", \"CLAWNET_OLLAMA_MODEL\"],\n ];\n\n for (const [configKey, envKey] of mapping) {\n const value = embedding[configKey];\n if (value !== undefined && process.env[envKey] === undefined) {\n process.env[envKey] = value;\n }\n }\n}\n\n/** Load config: CLI opts > env vars > settings file > defaults */\nexport function loadConfig(cliOpts: Partial<AgentConfig> = {}): AgentConfig {\n let fileConfig: Partial<AgentConfig> = {};\n\n log.info({ path: SETTINGS_FILE }, \"loading config\");\n\n if (existsSync(SETTINGS_FILE)) {\n try {\n fileConfig = JSON.parse(readFileSync(SETTINGS_FILE, \"utf-8\"));\n log.info(\n { hubUrl: fileConfig.hubUrl, hasToken: !!fileConfig.token, name: fileConfig.name },\n \"settings.json loaded\"\n );\n } catch (e) {\n log.warn({ err: e }, \"failed to parse settings.json\");\n }\n } else {\n log.warn(\"settings.json not found\");\n }\n\n // Apply structured embedding config to process.env\n if (fileConfig.embedding) {\n applyEmbeddingConfig(fileConfig.embedding);\n }\n\n const hubUrl =\n cliOpts.hubUrl ??\n process.env.CLAWNET_HUB_URL ??\n fileConfig.hubUrl ??\n DEFAULTS.hubUrl;\n\n const resolved = {\n hubUrl: normalizeHubUrl(hubUrl),\n token:\n cliOpts.token ??\n process.env.CLAWNET_TOKEN ??\n fileConfig.token ??\n DEFAULTS.token,\n name:\n cliOpts.name ??\n process.env.CLAWNET_NAME ??\n fileConfig.name ??\n DEFAULTS.name,\n backendType:\n (cliOpts.backendType as BackendType) ??\n (process.env.CLAWNET_BACKEND_TYPE as BackendType) ??\n (fileConfig.backendType as BackendType) ??\n DEFAULTS.backendType,\n embedding: fileConfig.embedding,\n };\n\n log.info(\n {\n hubUrl: resolved.hubUrl,\n hubUrlSource: cliOpts.hubUrl ? \"cli\" : process.env.CLAWNET_HUB_URL ? \"env\" : fileConfig.hubUrl ? \"file\" : \"default\",\n tokenSource: cliOpts.token ? \"cli\" : process.env.CLAWNET_TOKEN ? \"env\" : fileConfig.token ? \"file\" : \"default\",\n hasToken: !!resolved.token,\n },\n \"config resolved\"\n );\n\n return resolved;\n}\n\n/** Save config to ~/.clawnet/settings.json */\nexport function saveConfig(config: Partial<AgentConfig>): void {\n mkdirSync(CONFIG_DIR, { recursive: true });\n\n let existing: Partial<AgentConfig> = {};\n if (existsSync(SETTINGS_FILE)) {\n try {\n existing = JSON.parse(readFileSync(SETTINGS_FILE, \"utf-8\"));\n } catch {\n // ignore\n }\n }\n\n const merged = { ...existing, ...config };\n writeFileSync(SETTINGS_FILE, JSON.stringify(merged, null, 2) + \"\\n\");\n}\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/service/macos.ts"],"sourcesContent":["import { execSync, spawn } from \"child_process\";\nimport { existsSync, writeFileSync, unlinkSync, mkdirSync, chmodSync } from \"fs\";\nimport { join } from \"path\";\nimport { homedir } from \"os\";\nimport type { ServiceManager, ServiceStatus } from \"./types.js\";\nimport {\n SERVICE_LABEL,\n getLogDir,\n getNodePath,\n getCliPath,\n loadServiceConfig,\n type ServiceConfig,\n} from \"./config.js\";\n\nexport function getPlistPath(): string {\n return join(homedir(), \"Library\", \"LaunchAgents\", `${SERVICE_LABEL}.plist`);\n}\n\nfunction escapeXml(str: string): string {\n return str\n .replace(/&/g, \"&amp;\")\n .replace(/</g, \"&lt;\")\n .replace(/>/g, \"&gt;\")\n .replace(/\"/g, \"&quot;\")\n .replace(/'/g, \"&apos;\");\n}\n\nexport function generatePlist(config: ServiceConfig): string {\n const nodePath = getNodePath();\n const cliPath = getCliPath();\n const logDir = getLogDir();\n\n const envEntries: string[] = [];\n if (config.hubUrl) {\n envEntries.push(` <key>CLAWNET_HUB_URL</key>\\n <string>${escapeXml(config.hubUrl)}</string>`);\n }\n if (config.token) {\n envEntries.push(` <key>CLAWNET_TOKEN</key>\\n <string>${escapeXml(config.token)}</string>`);\n }\n if (config.name) {\n envEntries.push(` <key>CLAWNET_NAME</key>\\n <string>${escapeXml(config.name)}</string>`);\n }\n\n return `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n <key>Label</key>\n <string>${SERVICE_LABEL}</string>\n <key>ProgramArguments</key>\n <array>\n <string>${nodePath}</string>\n <string>${cliPath}</string>\n <string>start</string>\n <string>-f</string>\n </array>\n <key>WorkingDirectory</key>\n <string>${homedir()}</string>\n <key>EnvironmentVariables</key>\n <dict>\n${envEntries.join(\"\\n\")}\n </dict>\n <key>RunAtLoad</key>\n <true/>\n <key>KeepAlive</key>\n <dict>\n <key>SuccessfulExit</key>\n <false/>\n </dict>\n <key>ThrottleInterval</key>\n <integer>10</integer>\n <key>StandardOutPath</key>\n <string>${logDir}/out.log</string>\n <key>StandardErrorPath</key>\n <string>${logDir}/error.log</string>\n</dict>\n</plist>`;\n}\n\nexport class MacOSServiceManager implements ServiceManager {\n async install(): Promise<void> {\n const config = loadServiceConfig();\n const plistPath = getPlistPath();\n const logDir = getLogDir();\n const launchAgentsDir = join(homedir(), \"Library\", \"LaunchAgents\");\n\n if (existsSync(plistPath)) {\n try {\n execSync(`launchctl unload \"${plistPath}\"`, { stdio: \"ignore\" });\n } catch { /* ignore */ }\n }\n\n if (!existsSync(launchAgentsDir)) mkdirSync(launchAgentsDir, { recursive: true });\n if (!existsSync(logDir)) mkdirSync(logDir, { recursive: true });\n\n writeFileSync(plistPath, generatePlist(config), \"utf-8\");\n chmodSync(plistPath, 0o600);\n console.log(`✓ Service registered: ${plistPath}`);\n }\n\n async uninstall(): Promise<void> {\n const plistPath = getPlistPath();\n if (!existsSync(plistPath)) {\n console.log(\"Service not registered\");\n return;\n }\n try {\n execSync(`launchctl unload \"${plistPath}\"`, { stdio: \"ignore\" });\n } catch { /* ignore */ }\n unlinkSync(plistPath);\n console.log(\"✓ Service removed\");\n }\n\n async start(): Promise<void> {\n const plistPath = getPlistPath();\n if (!existsSync(plistPath)) {\n throw new Error(\"Service not registered. Run clawnet-agent enable first.\");\n }\n execSync(`launchctl load \"${plistPath}\"`, { stdio: \"inherit\" });\n console.log(\"✓ Service started\");\n }\n\n async stop(): Promise<void> {\n const plistPath = getPlistPath();\n if (!existsSync(plistPath)) {\n console.log(\"Service not registered\");\n return;\n }\n try {\n execSync(`launchctl unload \"${plistPath}\"`, { stdio: \"inherit\" });\n console.log(\"✓ Service stopped\");\n } catch {\n console.log(\"Service not running\");\n }\n }\n\n async restart(): Promise<void> {\n await this.stop();\n await this.start();\n }\n\n async status(): Promise<ServiceStatus> {\n try {\n const output = execSync(\n `launchctl list | grep ${SERVICE_LABEL}`,\n { encoding: \"utf-8\" }\n ).trim();\n if (!output) return { running: false };\n const [pidStr, exitCodeStr] = output.split(/\\s+/);\n const pid = pidStr === \"-\" ? undefined : parseInt(pidStr, 10);\n const exitCode = parseInt(exitCodeStr, 10);\n return { running: pid !== undefined, pid, exitCode };\n } catch {\n return { running: false };\n }\n }\n\n async printStatus(): Promise<void> {\n const s = await this.status();\n console.log(\"ClawNet Agent\");\n console.log(` Status: ${s.running ? \"Running ✓\" : \"Stopped ✗\"}`);\n if (s.pid) console.log(` PID: ${s.pid}`);\n if (s.exitCode !== undefined && !s.running) console.log(` Exit code: ${s.exitCode}`);\n console.log(\" Platform: macOS (launchd)\");\n }\n\n async logs(options: { follow?: boolean; lines?: number } = {}): Promise<void> {\n const logDir = getLogDir();\n const outLog = join(logDir, \"out.log\");\n const errLog = join(logDir, \"error.log\");\n\n const files: string[] = [];\n if (existsSync(outLog)) files.push(outLog);\n if (existsSync(errLog)) files.push(errLog);\n\n if (files.length === 0) {\n console.log(\"No logs yet\");\n return;\n }\n\n const lines = options.lines || 100;\n const args = options.follow\n ? [\"-f\", \"-n\", String(lines), ...files]\n : [\"-n\", String(lines), ...files];\n\n const child = spawn(\"tail\", args, { stdio: \"inherit\" });\n await new Promise<void>((resolve) => child.on(\"close\", resolve));\n }\n}\n"],"mappings":"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","names":[]}