@mclawnet/agent 0.5.9 → 0.6.2

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.
Files changed (81) hide show
  1. package/cli.js +168 -61
  2. package/dist/__tests__/cli.test.d.ts +2 -0
  3. package/dist/__tests__/cli.test.d.ts.map +1 -0
  4. package/dist/__tests__/service-config.test.d.ts +2 -0
  5. package/dist/__tests__/service-config.test.d.ts.map +1 -0
  6. package/dist/__tests__/service-linux.test.d.ts +2 -0
  7. package/dist/__tests__/service-linux.test.d.ts.map +1 -0
  8. package/dist/__tests__/service-macos.test.d.ts +2 -0
  9. package/dist/__tests__/service-macos.test.d.ts.map +1 -0
  10. package/dist/__tests__/service-windows.test.d.ts +2 -0
  11. package/dist/__tests__/service-windows.test.d.ts.map +1 -0
  12. package/dist/backend-adapter.d.ts +2 -0
  13. package/dist/backend-adapter.d.ts.map +1 -1
  14. package/dist/chunk-CBZIH6FY.js +93 -0
  15. package/dist/chunk-CBZIH6FY.js.map +1 -0
  16. package/dist/{chunk-KHPEQTWF.js → chunk-GLO5OZAY.js} +203 -213
  17. package/dist/chunk-GLO5OZAY.js.map +1 -0
  18. package/dist/chunk-RO47ET27.js +88 -0
  19. package/dist/chunk-RO47ET27.js.map +1 -0
  20. package/dist/hub-connection.d.ts.map +1 -1
  21. package/dist/index.js +5 -3
  22. package/dist/index.js.map +1 -1
  23. package/dist/linux-6AR7SXHW.js +176 -0
  24. package/dist/linux-6AR7SXHW.js.map +1 -0
  25. package/dist/macos-XVPWIH4C.js +174 -0
  26. package/dist/macos-XVPWIH4C.js.map +1 -0
  27. package/dist/service/config.d.ts +19 -0
  28. package/dist/service/config.d.ts.map +1 -0
  29. package/dist/service/index.d.ts +6 -0
  30. package/dist/service/index.d.ts.map +1 -0
  31. package/dist/service/index.js +47 -0
  32. package/dist/service/index.js.map +1 -0
  33. package/dist/service/linux.d.ts +18 -0
  34. package/dist/service/linux.d.ts.map +1 -0
  35. package/dist/service/macos.d.ts +18 -0
  36. package/dist/service/macos.d.ts.map +1 -0
  37. package/dist/service/types.d.ts +19 -0
  38. package/dist/service/types.d.ts.map +1 -0
  39. package/dist/service/windows.d.ts +18 -0
  40. package/dist/service/windows.d.ts.map +1 -0
  41. package/dist/session-manager.d.ts +4 -7
  42. package/dist/session-manager.d.ts.map +1 -1
  43. package/dist/skill-loader.d.ts +8 -0
  44. package/dist/skill-loader.d.ts.map +1 -0
  45. package/dist/start.d.ts.map +1 -1
  46. package/dist/start.js +2 -1
  47. package/dist/windows-NLONSCDA.js +165 -0
  48. package/dist/windows-NLONSCDA.js.map +1 -0
  49. package/package.json +7 -5
  50. package/skills/academic-search/SKILL.md +147 -0
  51. package/skills/architecture/SKILL.md +294 -0
  52. package/skills/changelog-generator/SKILL.md +112 -0
  53. package/skills/chart-visualization/SKILL.md +183 -0
  54. package/skills/code-review/SKILL.md +304 -0
  55. package/skills/codebase-health/SKILL.md +281 -0
  56. package/skills/consulting-analysis/SKILL.md +584 -0
  57. package/skills/content-research-writer/SKILL.md +546 -0
  58. package/skills/data-analysis/SKILL.md +194 -0
  59. package/skills/deep-research/SKILL.md +198 -0
  60. package/skills/docx/SKILL.md +211 -0
  61. package/skills/github-deep-research/SKILL.md +207 -0
  62. package/skills/image-generation/SKILL.md +209 -0
  63. package/skills/lead-research-assistant/SKILL.md +207 -0
  64. package/skills/mcp-builder/SKILL.md +304 -0
  65. package/skills/meeting-insights-analyzer/SKILL.md +335 -0
  66. package/skills/pair-programming/SKILL.md +196 -0
  67. package/skills/pdf/SKILL.md +309 -0
  68. package/skills/performance-analysis/SKILL.md +261 -0
  69. package/skills/podcast-generation/SKILL.md +224 -0
  70. package/skills/pptx/SKILL.md +497 -0
  71. package/skills/project-learnings/SKILL.md +280 -0
  72. package/skills/security-audit/SKILL.md +211 -0
  73. package/skills/skill-creator/SKILL.md +200 -0
  74. package/skills/technical-writing/SKILL.md +286 -0
  75. package/skills/testing/SKILL.md +363 -0
  76. package/skills/video-generation/SKILL.md +247 -0
  77. package/skills/web-design-guidelines/SKILL.md +203 -0
  78. package/skills/webapp-testing/SKILL.md +162 -0
  79. package/skills/workflow-automation/SKILL.md +299 -0
  80. package/skills/xlsx/SKILL.md +305 -0
  81. package/dist/chunk-KHPEQTWF.js.map +0 -1
package/cli.js CHANGED
@@ -1,74 +1,181 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- const args = process.argv.slice(2);
4
- const command = args[0] || "start";
5
-
6
- if (command === "start") {
7
- // Parse CLI flags
8
- const opts = {};
9
- for (let i = 1; i < args.length; i++) {
10
- if ((args[i] === "--hub-url" || args[i] === "--server") && args[i + 1]) {
11
- opts.hubUrl = args[++i];
12
- } else if (args[i] === "--token" && args[i + 1]) {
13
- opts.token = args[++i];
14
- } else if (args[i] === "--name" && args[i + 1]) {
15
- opts.name = args[++i];
16
- } else if (args[i] === "--backend" && args[i + 1]) {
17
- opts.backendType = args[++i];
18
- }
19
- }
3
+ import { Command } from "commander";
4
+ import { readFileSync } from "fs";
5
+
6
+ const pkg = JSON.parse(readFileSync(new URL("./package.json", import.meta.url), "utf-8"));
20
7
 
21
- // Default to claude-code adapter
22
- const backendType = opts.backendType || "claude-code";
8
+ const program = new Command();
23
9
 
24
- async function main() {
25
- let adapter;
10
+ program
11
+ .name("clawnet-agent")
12
+ .description("ClawNet Agent — intelligent agent daemon service")
13
+ .version(pkg.version);
26
14
 
27
- if (backendType === "claude-code") {
28
- try {
29
- const { ClaudeCodeAdapter } = await import("@mclawnet/claude-adapter");
30
- adapter = new ClaudeCodeAdapter();
31
- } catch (err) {
32
- console.error("[clawnet] Failed to load @mclawnet/claude-adapter:", err.message);
33
- console.error("[clawnet] Install it: pnpm add @mclawnet/claude-adapter");
15
+ // === start (default command) ===
16
+ program
17
+ .command("start", { isDefault: true })
18
+ .description("Start Agent (daemon mode by default, use -f for foreground)")
19
+ .option("-f, --foreground", "Run in foreground (for development/debugging)")
20
+ .option("--hub-url <url>", "Hub WebSocket URL")
21
+ .option("--token <token>", "Agent token")
22
+ .option("--name <name>", "Agent name")
23
+ .option("--backend <type>", "Backend type", "claude-code")
24
+ .action(async (opts) => {
25
+ if (opts.foreground) {
26
+ // Foreground mode: directly run agent (existing behavior)
27
+ const config = {};
28
+ if (opts.hubUrl) config.hubUrl = opts.hubUrl;
29
+ if (opts.token) config.token = opts.token;
30
+ if (opts.name) config.name = opts.name;
31
+ if (opts.backend) config.backendType = opts.backend;
32
+
33
+ let adapter;
34
+ const backendType = opts.backend || "claude-code";
35
+ if (backendType === "claude-code") {
36
+ try {
37
+ const { ClaudeCodeAdapter } = await import("@mclawnet/claude-adapter");
38
+ adapter = new ClaudeCodeAdapter();
39
+ } catch (err) {
40
+ console.error("[clawnet] Failed to load @mclawnet/claude-adapter:", err.message);
41
+ process.exit(1);
42
+ }
43
+ } else {
44
+ console.error(`[clawnet] Unknown backend type: ${backendType}`);
34
45
  process.exit(1);
35
46
  }
47
+
48
+ const { startAgent } = await import("./dist/start.js");
49
+ await startAgent({ config, adapter });
36
50
  } else {
37
- console.error(`[clawnet] Unknown backend type: ${backendType}`);
38
- process.exit(1);
51
+ // Daemon mode: register service + start
52
+ const { getServiceManager, mergeServiceConfig, saveServiceConfig, validateServiceConfig } =
53
+ await import("./dist/service/index.js");
54
+
55
+ const cliOpts = {};
56
+ if (opts.hubUrl) cliOpts.hubUrl = opts.hubUrl;
57
+ if (opts.token) cliOpts.token = opts.token;
58
+ if (opts.name) cliOpts.name = opts.name;
59
+
60
+ const config = mergeServiceConfig(cliOpts);
61
+ validateServiceConfig(config);
62
+ saveServiceConfig(config);
63
+
64
+ const manager = await getServiceManager();
65
+ const status = await manager.status();
66
+
67
+ if (status.running) {
68
+ console.log(`Agent is already running (PID: ${status.pid}). Use 'restart' to restart.`);
69
+ return;
70
+ }
71
+
72
+ await manager.install();
73
+ await manager.start();
39
74
  }
75
+ });
40
76
 
41
- const { startAgent } = await import("./dist/start.js");
42
- await startAgent({ config: opts, adapter });
43
- }
77
+ // === stop ===
78
+ program
79
+ .command("stop")
80
+ .description("Stop Agent service")
81
+ .action(async () => {
82
+ const { getServiceManager } = await import("./dist/service/index.js");
83
+ const manager = await getServiceManager();
84
+ await manager.stop();
85
+ });
44
86
 
45
- main().catch((err) => {
46
- console.error("[clawnet] Fatal:", err);
47
- process.exit(1);
87
+ // === restart ===
88
+ program
89
+ .command("restart")
90
+ .description("Restart Agent service")
91
+ .action(async () => {
92
+ const { getServiceManager } = await import("./dist/service/index.js");
93
+ const manager = await getServiceManager();
94
+ await manager.restart();
48
95
  });
49
- } else if (command === "config") {
50
- const subCmd = args[1];
51
- import("./dist/index.js").then(({ loadConfig, saveConfig }) => {
52
- if (subCmd === "set" && args[2] && args[3]) {
53
- saveConfig({ [args[2]]: args[3] });
54
- console.log(`Set ${args[2]} = ${args[3]}`);
55
- } else if (subCmd === "show") {
56
- console.log(JSON.stringify(loadConfig(), null, 2));
57
- } else {
58
- console.log("Usage: clawnet-agent config set <key> <value>");
59
- console.log(" clawnet-agent config show");
60
- }
96
+
97
+ // === enable ===
98
+ program
99
+ .command("enable")
100
+ .description("Register system service (without starting)")
101
+ .option("--hub-url <url>", "Hub WebSocket URL")
102
+ .option("--token <token>", "Agent token")
103
+ .option("--name <name>", "Agent name")
104
+ .action(async (opts) => {
105
+ const { getServiceManager, mergeServiceConfig, saveServiceConfig, validateServiceConfig } =
106
+ await import("./dist/service/index.js");
107
+
108
+ const cliOpts = {};
109
+ if (opts.hubUrl) cliOpts.hubUrl = opts.hubUrl;
110
+ if (opts.token) cliOpts.token = opts.token;
111
+ if (opts.name) cliOpts.name = opts.name;
112
+
113
+ const config = mergeServiceConfig(cliOpts);
114
+ validateServiceConfig(config);
115
+ saveServiceConfig(config);
116
+
117
+ const manager = await getServiceManager();
118
+ await manager.install();
119
+ });
120
+
121
+ // === disable ===
122
+ program
123
+ .command("disable")
124
+ .description("Stop and remove system service")
125
+ .action(async () => {
126
+ const { getServiceManager } = await import("./dist/service/index.js");
127
+ const manager = await getServiceManager();
128
+ await manager.uninstall();
129
+ });
130
+
131
+ // === status ===
132
+ program
133
+ .command("status")
134
+ .description("Show Agent status")
135
+ .action(async () => {
136
+ const { getServiceManager } = await import("./dist/service/index.js");
137
+ const manager = await getServiceManager();
138
+ await manager.printStatus();
61
139
  });
62
- } else {
63
- console.log("Usage: clawnet-agent [start|config] [options]");
64
- console.log("");
65
- console.log("Commands:");
66
- console.log(" start Start the agent (default)");
67
- console.log(" config View/set configuration");
68
- console.log("");
69
- console.log("Options:");
70
- console.log(" --server <url> Hub WebSocket URL (alias: --hub-url)");
71
- console.log(" --token <token> Agent token");
72
- console.log(" --name <name> Agent name");
73
- console.log(" --backend <type> Backend type (claude-code)");
74
- }
140
+
141
+ // === logs ===
142
+ program
143
+ .command("logs")
144
+ .description("View Agent logs")
145
+ .option("-f, --follow", "Follow log output in real-time")
146
+ .option("-n, --lines <number>", "Number of lines to show", "100")
147
+ .action(async (opts) => {
148
+ const { getServiceManager } = await import("./dist/service/index.js");
149
+ const manager = await getServiceManager();
150
+ await manager.logs({
151
+ follow: opts.follow,
152
+ lines: parseInt(opts.lines, 10),
153
+ });
154
+ });
155
+
156
+ // === config ===
157
+ const configCmd = program
158
+ .command("config")
159
+ .description("View or modify configuration");
160
+
161
+ configCmd
162
+ .command("show")
163
+ .description("Show current configuration")
164
+ .action(async () => {
165
+ const { loadConfig } = await import("./dist/index.js");
166
+ console.log(JSON.stringify(loadConfig(), null, 2));
167
+ });
168
+
169
+ configCmd
170
+ .command("set <key> <value>")
171
+ .description("Set a configuration value")
172
+ .action(async (key, value) => {
173
+ const { saveConfig } = await import("./dist/index.js");
174
+ saveConfig({ [key]: value });
175
+ console.log(`Set ${key} = ${value}`);
176
+ });
177
+
178
+ program.parseAsync(process.argv).catch((err) => {
179
+ console.error("[clawnet] Fatal:", err.message || err);
180
+ process.exit(1);
181
+ });
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=cli.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/cli.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=service-config.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service-config.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/service-config.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=service-linux.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service-linux.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/service-linux.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=service-macos.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service-macos.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/service-macos.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=service-windows.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service-windows.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/service-windows.test.ts"],"names":[],"mappings":""}
@@ -29,6 +29,8 @@ export interface SpawnOptions {
29
29
  mcpConfigPath?: string;
30
30
  /** Memory system role ID. When set, SessionManager auto-injects memory prompt + MCP config */
31
31
  roleId?: string;
32
+ /** Extra directories to mount via --add-dir */
33
+ additionalDirs?: string[];
32
34
  }
33
35
  export interface BackendAdapter {
34
36
  /** Backend type identifier */
@@ -1 +1 @@
1
- {"version":3,"file":"backend-adapter.d.ts","sourceRoot":"","sources":["../src/backend-adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,MAAM,WAAW,cAAc;IAC7B,kDAAkD;IAClD,EAAE,EAAE,MAAM,CAAC;IACX,yCAAyC;IACzC,OAAO,EAAE,MAAM,CAAC;IAChB,+BAA+B;IAC/B,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACvB;AAED,MAAM,WAAW,YAAY;IAC3B,yBAAyB;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,gDAAgD;IAChD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,6DAA6D;IAC7D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,iEAAiE;IACjE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,+CAA+C;IAC/C,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,oDAAoD;IACpD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,8FAA8F;IAC9F,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,cAAc;IAC7B,8BAA8B;IAC9B,IAAI,EAAE,MAAM,CAAC;IAEb,kCAAkC;IAClC,KAAK,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;IAEtD,qCAAqC;IACrC,IAAI,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE7C,6CAA6C;IAC7C,IAAI,CAAC,OAAO,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAEnD,oDAAoD;IACpD,QAAQ,CAAC,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,IAAI,GAAG,IAAI,CAAC;IAEzE,qCAAqC;IACrC,cAAc,CAAC,CACb,OAAO,EAAE,cAAc,EACvB,OAAO,EAAE,CAAC,IAAI,EAAE;QACd,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,YAAY,CAAC,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,CAAA;SAAE,CAAC;KAChD,KAAK,IAAI,GACT,IAAI,CAAC;IAER,6BAA6B;IAC7B,OAAO,CAAC,CAAC,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,GAAG,IAAI,CAAC;CAC1E"}
1
+ {"version":3,"file":"backend-adapter.d.ts","sourceRoot":"","sources":["../src/backend-adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,MAAM,WAAW,cAAc;IAC7B,kDAAkD;IAClD,EAAE,EAAE,MAAM,CAAC;IACX,yCAAyC;IACzC,OAAO,EAAE,MAAM,CAAC;IAChB,+BAA+B;IAC/B,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACvB;AAED,MAAM,WAAW,YAAY;IAC3B,yBAAyB;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,gDAAgD;IAChD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,6DAA6D;IAC7D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,iEAAiE;IACjE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,+CAA+C;IAC/C,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,oDAAoD;IACpD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,8FAA8F;IAC9F,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,+CAA+C;IAC/C,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;CAC3B;AAED,MAAM,WAAW,cAAc;IAC7B,8BAA8B;IAC9B,IAAI,EAAE,MAAM,CAAC;IAEb,kCAAkC;IAClC,KAAK,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;IAEtD,qCAAqC;IACrC,IAAI,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE7C,6CAA6C;IAC7C,IAAI,CAAC,OAAO,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAEnD,oDAAoD;IACpD,QAAQ,CAAC,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,IAAI,GAAG,IAAI,CAAC;IAEzE,qCAAqC;IACrC,cAAc,CAAC,CACb,OAAO,EAAE,cAAc,EACvB,OAAO,EAAE,CAAC,IAAI,EAAE;QACd,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,YAAY,CAAC,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,CAAA;SAAE,CAAC;KAChD,KAAK,IAAI,GACT,IAAI,CAAC;IAER,6BAA6B;IAC7B,OAAO,CAAC,CAAC,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,GAAG,IAAI,CAAC;CAC1E"}
@@ -0,0 +1,93 @@
1
+ // src/config.ts
2
+ import { readFileSync, writeFileSync, mkdirSync, existsSync } from "fs";
3
+ import { join } from "path";
4
+ import { homedir, hostname } from "os";
5
+ import { createLogger } from "@mclawnet/logger";
6
+ var log = createLogger({ module: "config" });
7
+ var CONFIG_DIR = join(homedir(), ".clawnet");
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";
10
+ var DEFAULTS = {
11
+ hubUrl: DEFAULT_HUB_URL,
12
+ token: "",
13
+ name: hostname(),
14
+ backendType: "claude-code"
15
+ };
16
+ function normalizeHubUrl(url) {
17
+ url = url.replace(/^https:\/\//, "wss://").replace(/^http:\/\//, "ws://");
18
+ if (!/^wss?:\/\//.test(url)) url = "wss://" + url;
19
+ if (url.endsWith("/ws/agent")) return url;
20
+ return url.replace(/\/+$/, "") + "/ws/agent";
21
+ }
22
+ function applyEmbeddingConfig(embedding) {
23
+ const mapping = [
24
+ ["provider", "CLAWNET_EMBEDDING_PROVIDER"],
25
+ ["openaiBaseUrl", "CLAWNET_OPENAI_BASE_URL"],
26
+ ["openaiApiKey", "CLAWNET_OPENAI_API_KEY"],
27
+ ["openaiModel", "CLAWNET_OPENAI_EMBEDDING_MODEL"],
28
+ ["ollamaUrl", "CLAWNET_OLLAMA_URL"],
29
+ ["ollamaModel", "CLAWNET_OLLAMA_MODEL"]
30
+ ];
31
+ for (const [configKey, envKey] of mapping) {
32
+ const value = embedding[configKey];
33
+ if (value !== void 0 && process.env[envKey] === void 0) {
34
+ process.env[envKey] = value;
35
+ }
36
+ }
37
+ }
38
+ function loadConfig(cliOpts = {}) {
39
+ let fileConfig = {};
40
+ log.info({ path: SETTINGS_FILE }, "loading config");
41
+ if (existsSync(SETTINGS_FILE)) {
42
+ try {
43
+ fileConfig = JSON.parse(readFileSync(SETTINGS_FILE, "utf-8"));
44
+ log.info(
45
+ { hubUrl: fileConfig.hubUrl, hasToken: !!fileConfig.token, name: fileConfig.name },
46
+ "settings.json loaded"
47
+ );
48
+ } catch (e) {
49
+ log.warn({ err: e }, "failed to parse settings.json");
50
+ }
51
+ } else {
52
+ log.warn("settings.json not found");
53
+ }
54
+ if (fileConfig.embedding) {
55
+ applyEmbeddingConfig(fileConfig.embedding);
56
+ }
57
+ const hubUrl = cliOpts.hubUrl ?? process.env.CLAWNET_HUB_URL ?? fileConfig.hubUrl ?? DEFAULTS.hubUrl;
58
+ const resolved = {
59
+ hubUrl: normalizeHubUrl(hubUrl),
60
+ token: cliOpts.token ?? process.env.CLAWNET_TOKEN ?? fileConfig.token ?? DEFAULTS.token,
61
+ name: cliOpts.name ?? process.env.CLAWNET_NAME ?? fileConfig.name ?? DEFAULTS.name,
62
+ backendType: cliOpts.backendType ?? process.env.CLAWNET_BACKEND_TYPE ?? fileConfig.backendType ?? DEFAULTS.backendType,
63
+ embedding: fileConfig.embedding
64
+ };
65
+ log.info(
66
+ {
67
+ hubUrl: resolved.hubUrl,
68
+ hubUrlSource: cliOpts.hubUrl ? "cli" : process.env.CLAWNET_HUB_URL ? "env" : fileConfig.hubUrl ? "file" : "default",
69
+ tokenSource: cliOpts.token ? "cli" : process.env.CLAWNET_TOKEN ? "env" : fileConfig.token ? "file" : "default",
70
+ hasToken: !!resolved.token
71
+ },
72
+ "config resolved"
73
+ );
74
+ return resolved;
75
+ }
76
+ function saveConfig(config) {
77
+ mkdirSync(CONFIG_DIR, { recursive: true });
78
+ let existing = {};
79
+ if (existsSync(SETTINGS_FILE)) {
80
+ try {
81
+ existing = JSON.parse(readFileSync(SETTINGS_FILE, "utf-8"));
82
+ } catch {
83
+ }
84
+ }
85
+ const merged = { ...existing, ...config };
86
+ writeFileSync(SETTINGS_FILE, JSON.stringify(merged, null, 2) + "\n");
87
+ }
88
+
89
+ export {
90
+ loadConfig,
91
+ saveConfig
92
+ };
93
+ //# sourceMappingURL=chunk-CBZIH6FY.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 || \"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":[]}