nextclaw-core 0.4.3 → 0.4.5
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/dist/index.d.ts +177 -149
- package/dist/index.js +582 -162
- package/package.json +3 -2
package/dist/index.js
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
// src/agent/context.ts
|
|
2
|
-
import { readFileSync as
|
|
2
|
+
import { readFileSync as readFileSync4, existsSync as existsSync4 } from "fs";
|
|
3
3
|
import { join as join3, extname } from "path";
|
|
4
4
|
|
|
5
5
|
// src/agent/memory.ts
|
|
6
|
-
import { readFileSync, writeFileSync, existsSync as existsSync2, readdirSync } from "fs";
|
|
6
|
+
import { readFileSync as readFileSync2, writeFileSync, existsSync as existsSync2, readdirSync } from "fs";
|
|
7
7
|
import { join } from "path";
|
|
8
8
|
|
|
9
9
|
// src/utils/helpers.ts
|
|
10
|
-
import { existsSync, mkdirSync } from "fs";
|
|
10
|
+
import { existsSync, mkdirSync, readFileSync } from "fs";
|
|
11
11
|
import { homedir } from "os";
|
|
12
12
|
import { resolve } from "path";
|
|
13
|
+
import { fileURLToPath } from "url";
|
|
13
14
|
|
|
14
15
|
// src/config/brand.ts
|
|
15
16
|
var ENV_APP_NAME_KEY = "NEXTCLAW_APP_NAME";
|
|
@@ -85,6 +86,17 @@ function expandHome(value) {
|
|
|
85
86
|
}
|
|
86
87
|
return value;
|
|
87
88
|
}
|
|
89
|
+
function getPackageVersion() {
|
|
90
|
+
try {
|
|
91
|
+
const dir = resolve(fileURLToPath(new URL(".", import.meta.url)));
|
|
92
|
+
const pkgPath = resolve(dir, "..", "..", "package.json");
|
|
93
|
+
const raw = readFileSync(pkgPath, "utf-8");
|
|
94
|
+
const parsed = JSON.parse(raw);
|
|
95
|
+
return typeof parsed.version === "string" ? parsed.version : "0.0.0";
|
|
96
|
+
} catch {
|
|
97
|
+
return "0.0.0";
|
|
98
|
+
}
|
|
99
|
+
}
|
|
88
100
|
|
|
89
101
|
// src/agent/memory.ts
|
|
90
102
|
var MemoryStore = class {
|
|
@@ -103,7 +115,7 @@ var MemoryStore = class {
|
|
|
103
115
|
readToday() {
|
|
104
116
|
const todayFile = this.getTodayFile();
|
|
105
117
|
if (existsSync2(todayFile)) {
|
|
106
|
-
return
|
|
118
|
+
return readFileSync2(todayFile, "utf-8");
|
|
107
119
|
}
|
|
108
120
|
return "";
|
|
109
121
|
}
|
|
@@ -111,7 +123,7 @@ var MemoryStore = class {
|
|
|
111
123
|
const todayFile = this.getTodayFile();
|
|
112
124
|
let nextContent = content;
|
|
113
125
|
if (existsSync2(todayFile)) {
|
|
114
|
-
const existing =
|
|
126
|
+
const existing = readFileSync2(todayFile, "utf-8");
|
|
115
127
|
nextContent = `${existing}
|
|
116
128
|
${content}`;
|
|
117
129
|
} else {
|
|
@@ -124,13 +136,13 @@ ${content}`;
|
|
|
124
136
|
}
|
|
125
137
|
readLongTerm() {
|
|
126
138
|
if (existsSync2(this.memoryFile)) {
|
|
127
|
-
return
|
|
139
|
+
return readFileSync2(this.memoryFile, "utf-8");
|
|
128
140
|
}
|
|
129
141
|
return "";
|
|
130
142
|
}
|
|
131
143
|
readWorkspaceMemory() {
|
|
132
144
|
if (existsSync2(this.workspaceMemoryFile)) {
|
|
133
|
-
return
|
|
145
|
+
return readFileSync2(this.workspaceMemoryFile, "utf-8");
|
|
134
146
|
}
|
|
135
147
|
return "";
|
|
136
148
|
}
|
|
@@ -146,7 +158,7 @@ ${content}`;
|
|
|
146
158
|
const dateStr = date.toISOString().slice(0, 10);
|
|
147
159
|
const path = join(this.memoryDir, `${dateStr}.md`);
|
|
148
160
|
if (existsSync2(path)) {
|
|
149
|
-
memories.push(
|
|
161
|
+
memories.push(readFileSync2(path, "utf-8"));
|
|
150
162
|
}
|
|
151
163
|
}
|
|
152
164
|
return memories.length ? memories.join("\n\n---\n\n") : "";
|
|
@@ -179,10 +191,10 @@ ${today}`);
|
|
|
179
191
|
};
|
|
180
192
|
|
|
181
193
|
// src/agent/skills.ts
|
|
182
|
-
import { readFileSync as
|
|
194
|
+
import { readFileSync as readFileSync3, existsSync as existsSync3, readdirSync as readdirSync2 } from "fs";
|
|
183
195
|
import { join as join2 } from "path";
|
|
184
|
-
import { fileURLToPath } from "url";
|
|
185
|
-
var BUILTIN_SKILLS_DIR = join2(
|
|
196
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
197
|
+
var BUILTIN_SKILLS_DIR = join2(fileURLToPath2(new URL(".", import.meta.url)), "skills");
|
|
186
198
|
var SkillsLoader = class {
|
|
187
199
|
constructor(workspace, builtinSkillsDir) {
|
|
188
200
|
this.workspace = workspace;
|
|
@@ -223,11 +235,11 @@ var SkillsLoader = class {
|
|
|
223
235
|
loadSkill(name) {
|
|
224
236
|
const workspaceSkill = join2(this.workspaceSkills, name, "SKILL.md");
|
|
225
237
|
if (existsSync3(workspaceSkill)) {
|
|
226
|
-
return
|
|
238
|
+
return readFileSync3(workspaceSkill, "utf-8");
|
|
227
239
|
}
|
|
228
240
|
const builtinSkill = join2(this.builtinSkills, name, "SKILL.md");
|
|
229
241
|
if (existsSync3(builtinSkill)) {
|
|
230
|
-
return
|
|
242
|
+
return readFileSync3(builtinSkill, "utf-8");
|
|
231
243
|
}
|
|
232
244
|
return null;
|
|
233
245
|
}
|
|
@@ -601,7 +613,7 @@ Your workspace is at: ${this.workspace}
|
|
|
601
613
|
for (const filename of fileList) {
|
|
602
614
|
const filePath = join3(this.workspace, filename);
|
|
603
615
|
if (existsSync4(filePath)) {
|
|
604
|
-
const raw =
|
|
616
|
+
const raw = readFileSync4(filePath, "utf-8").trim();
|
|
605
617
|
if (!raw) {
|
|
606
618
|
continue;
|
|
607
619
|
}
|
|
@@ -674,7 +686,7 @@ ${truncated}`;
|
|
|
674
686
|
continue;
|
|
675
687
|
}
|
|
676
688
|
try {
|
|
677
|
-
const b64 =
|
|
689
|
+
const b64 = readFileSync4(path).toString("base64");
|
|
678
690
|
images.push({ type: "image_url", image_url: { url: `data:${mime};base64,${b64}` } });
|
|
679
691
|
} catch {
|
|
680
692
|
continue;
|
|
@@ -746,7 +758,7 @@ var ToolRegistry = class {
|
|
|
746
758
|
};
|
|
747
759
|
|
|
748
760
|
// src/agent/tools/filesystem.ts
|
|
749
|
-
import { readFileSync as
|
|
761
|
+
import { readFileSync as readFileSync5, writeFileSync as writeFileSync2, existsSync as existsSync5, readdirSync as readdirSync3, statSync } from "fs";
|
|
750
762
|
import { resolve as resolve2, dirname } from "path";
|
|
751
763
|
|
|
752
764
|
// src/agent/tools/base.ts
|
|
@@ -861,7 +873,7 @@ var ReadFileTool = class extends Tool {
|
|
|
861
873
|
if (!existsSync5(path)) {
|
|
862
874
|
return `Error: File not found: ${path}`;
|
|
863
875
|
}
|
|
864
|
-
return
|
|
876
|
+
return readFileSync5(path, "utf-8");
|
|
865
877
|
}
|
|
866
878
|
};
|
|
867
879
|
var WriteFileTool = class extends Tool {
|
|
@@ -925,7 +937,7 @@ var EditFileTool = class extends Tool {
|
|
|
925
937
|
}
|
|
926
938
|
const oldText = String(params.oldText ?? "");
|
|
927
939
|
const newText = String(params.newText ?? "");
|
|
928
|
-
const content =
|
|
940
|
+
const content = readFileSync5(path, "utf-8");
|
|
929
941
|
if (!content.includes(oldText)) {
|
|
930
942
|
return "Error: Text to replace not found";
|
|
931
943
|
}
|
|
@@ -982,16 +994,17 @@ var ExecTool = class extends Tool {
|
|
|
982
994
|
"\\brm\\s+-[rf]{1,2}\\b",
|
|
983
995
|
"\\bdel\\s+/[fq]\\b",
|
|
984
996
|
"\\brmdir\\s+/s\\b",
|
|
985
|
-
"\\b(format|mkfs|diskpart)\\b",
|
|
986
997
|
"\\bdd\\s+if=",
|
|
987
998
|
">\\s*/dev/sd",
|
|
988
999
|
"\\b(shutdown|reboot|poweroff)\\b",
|
|
989
1000
|
":\\(\\)\\s*\\{.*\\};\\s*:"
|
|
990
1001
|
]).map((pattern) => new RegExp(pattern, "i"));
|
|
991
1002
|
this.allowPatterns = (options.allowPatterns ?? []).map((pattern) => new RegExp(pattern, "i"));
|
|
1003
|
+
this.dangerousCommands = ["format", "diskpart", "mkfs"];
|
|
992
1004
|
}
|
|
993
1005
|
denyPatterns;
|
|
994
1006
|
allowPatterns;
|
|
1007
|
+
dangerousCommands;
|
|
995
1008
|
get name() {
|
|
996
1009
|
return "exec";
|
|
997
1010
|
}
|
|
@@ -1037,6 +1050,9 @@ ${stderr}`);
|
|
|
1037
1050
|
}
|
|
1038
1051
|
guardCommand(command, cwd) {
|
|
1039
1052
|
const normalized = command.trim().toLowerCase();
|
|
1053
|
+
if (this.isDangerousCommand(normalized)) {
|
|
1054
|
+
return "Error: Command blocked by safety guard (dangerous pattern detected)";
|
|
1055
|
+
}
|
|
1040
1056
|
for (const pattern of this.denyPatterns) {
|
|
1041
1057
|
if (pattern.test(normalized)) {
|
|
1042
1058
|
return "Error: Command blocked by safety guard (dangerous pattern detected)";
|
|
@@ -1062,6 +1078,26 @@ ${stderr}`);
|
|
|
1062
1078
|
}
|
|
1063
1079
|
return null;
|
|
1064
1080
|
}
|
|
1081
|
+
isDangerousCommand(command) {
|
|
1082
|
+
const segments = command.split(/\s*(?:\|\||&&|;|\|)\s*/);
|
|
1083
|
+
for (const segment2 of segments) {
|
|
1084
|
+
const match = segment2.trim().match(/^(?:sudo\s+)?([^\s]+)/i);
|
|
1085
|
+
if (!match) {
|
|
1086
|
+
continue;
|
|
1087
|
+
}
|
|
1088
|
+
const token = match[1]?.toLowerCase() ?? "";
|
|
1089
|
+
if (!token) {
|
|
1090
|
+
continue;
|
|
1091
|
+
}
|
|
1092
|
+
if (this.dangerousCommands.includes(token)) {
|
|
1093
|
+
return true;
|
|
1094
|
+
}
|
|
1095
|
+
if (token.startsWith("mkfs")) {
|
|
1096
|
+
return true;
|
|
1097
|
+
}
|
|
1098
|
+
}
|
|
1099
|
+
return false;
|
|
1100
|
+
}
|
|
1065
1101
|
};
|
|
1066
1102
|
function truncateOutput(result, maxLen = 1e4) {
|
|
1067
1103
|
if (result.length <= maxLen) {
|
|
@@ -1646,7 +1682,7 @@ var SessionsSendTool = class extends Tool {
|
|
|
1646
1682
|
};
|
|
1647
1683
|
|
|
1648
1684
|
// src/agent/tools/memory.ts
|
|
1649
|
-
import { existsSync as existsSync6, readFileSync as
|
|
1685
|
+
import { existsSync as existsSync6, readFileSync as readFileSync6, readdirSync as readdirSync4 } from "fs";
|
|
1650
1686
|
import { join as join4, resolve as resolve4 } from "path";
|
|
1651
1687
|
var DEFAULT_LIMIT2 = 20;
|
|
1652
1688
|
var DEFAULT_CONTEXT_LINES = 0;
|
|
@@ -1711,7 +1747,7 @@ var MemorySearchTool = class extends Tool {
|
|
|
1711
1747
|
const results = [];
|
|
1712
1748
|
const files = getMemoryFiles(this.workspace);
|
|
1713
1749
|
for (const filePath of files) {
|
|
1714
|
-
const content =
|
|
1750
|
+
const content = readFileSync6(filePath, "utf-8");
|
|
1715
1751
|
const lines = content.split("\n");
|
|
1716
1752
|
for (let i = 0; i < lines.length; i += 1) {
|
|
1717
1753
|
if (lines[i].toLowerCase().includes(lowerQuery)) {
|
|
@@ -1775,7 +1811,7 @@ var MemoryGetTool = class extends Tool {
|
|
|
1775
1811
|
if (!existsSync6(resolvedPath)) {
|
|
1776
1812
|
return `Error: file not found: ${resolvedPath}`;
|
|
1777
1813
|
}
|
|
1778
|
-
const content =
|
|
1814
|
+
const content = readFileSync6(resolvedPath, "utf-8");
|
|
1779
1815
|
const lines = content.split("\n");
|
|
1780
1816
|
const startLine = toInt2(params.from ?? params.startLine, 1);
|
|
1781
1817
|
const requestedLines = toInt2(params.lines ?? params.endLine, Math.max(lines.length - startLine + 1, 1));
|
|
@@ -2244,7 +2280,7 @@ When you have completed the task, provide a clear summary of your findings or ac
|
|
|
2244
2280
|
};
|
|
2245
2281
|
|
|
2246
2282
|
// src/session/manager.ts
|
|
2247
|
-
import { readFileSync as
|
|
2283
|
+
import { readFileSync as readFileSync7, writeFileSync as writeFileSync3, existsSync as existsSync7, readdirSync as readdirSync5, unlinkSync } from "fs";
|
|
2248
2284
|
import { join as join5 } from "path";
|
|
2249
2285
|
var SessionManager = class {
|
|
2250
2286
|
constructor(workspace) {
|
|
@@ -2326,7 +2362,7 @@ var SessionManager = class {
|
|
|
2326
2362
|
return null;
|
|
2327
2363
|
}
|
|
2328
2364
|
try {
|
|
2329
|
-
const lines =
|
|
2365
|
+
const lines = readFileSync7(path, "utf-8").split("\n").filter(Boolean);
|
|
2330
2366
|
const messages = [];
|
|
2331
2367
|
let metadata = {};
|
|
2332
2368
|
let createdAt = /* @__PURE__ */ new Date();
|
|
@@ -2385,7 +2421,7 @@ var SessionManager = class {
|
|
|
2385
2421
|
continue;
|
|
2386
2422
|
}
|
|
2387
2423
|
const path = join5(this.sessionsDir, entry.name);
|
|
2388
|
-
const firstLine =
|
|
2424
|
+
const firstLine = readFileSync7(path, "utf-8").split("\n")[0];
|
|
2389
2425
|
if (!firstLine) {
|
|
2390
2426
|
continue;
|
|
2391
2427
|
}
|
|
@@ -3610,7 +3646,7 @@ function parseMdTable(tableText) {
|
|
|
3610
3646
|
import { io } from "socket.io-client";
|
|
3611
3647
|
import { fetch as fetch5 } from "undici";
|
|
3612
3648
|
import { join as join8 } from "path";
|
|
3613
|
-
import { mkdirSync as mkdirSync4, existsSync as existsSync9, readFileSync as
|
|
3649
|
+
import { mkdirSync as mkdirSync4, existsSync as existsSync9, readFileSync as readFileSync8, writeFileSync as writeFileSync5 } from "fs";
|
|
3614
3650
|
var MAX_SEEN_MESSAGE_IDS = 2e3;
|
|
3615
3651
|
var CURSOR_SAVE_DEBOUNCE_MS = 500;
|
|
3616
3652
|
var AsyncLock = class {
|
|
@@ -4323,7 +4359,7 @@ var MochatChannel = class extends BaseChannel {
|
|
|
4323
4359
|
return;
|
|
4324
4360
|
}
|
|
4325
4361
|
try {
|
|
4326
|
-
const raw =
|
|
4362
|
+
const raw = readFileSync8(this.cursorPath, "utf-8");
|
|
4327
4363
|
const data = JSON.parse(raw);
|
|
4328
4364
|
const cursors = data.cursors;
|
|
4329
4365
|
if (cursors && typeof cursors === "object") {
|
|
@@ -5279,12 +5315,13 @@ var ChannelManager = class {
|
|
|
5279
5315
|
};
|
|
5280
5316
|
|
|
5281
5317
|
// src/config/loader.ts
|
|
5282
|
-
import { readFileSync as
|
|
5318
|
+
import { readFileSync as readFileSync9, writeFileSync as writeFileSync6, existsSync as existsSync10, mkdirSync as mkdirSync5 } from "fs";
|
|
5283
5319
|
import { resolve as resolve5 } from "path";
|
|
5284
|
-
import { z as
|
|
5320
|
+
import { z as z3 } from "zod";
|
|
5285
5321
|
|
|
5286
5322
|
// src/config/schema.ts
|
|
5287
|
-
import { z } from "zod";
|
|
5323
|
+
import { z as z2 } from "zod";
|
|
5324
|
+
import { zodToJsonSchema } from "zod-to-json-schema";
|
|
5288
5325
|
|
|
5289
5326
|
// src/providers/registry.ts
|
|
5290
5327
|
var PROVIDERS = [
|
|
@@ -5517,117 +5554,419 @@ function providerLabel(spec) {
|
|
|
5517
5554
|
return spec.displayName || spec.name;
|
|
5518
5555
|
}
|
|
5519
5556
|
|
|
5557
|
+
// src/config/schema.hints.ts
|
|
5558
|
+
import { z } from "zod";
|
|
5559
|
+
|
|
5560
|
+
// src/config/schema.help.ts
|
|
5561
|
+
var FIELD_HELP = {
|
|
5562
|
+
"agents.defaults.workspace": "Workspace directory for agent context files and memory.",
|
|
5563
|
+
"agents.defaults.model": "Default model identifier used by the agent.",
|
|
5564
|
+
"agents.defaults.maxTokens": "Maximum tokens per response.",
|
|
5565
|
+
"agents.defaults.temperature": "Sampling temperature for model responses.",
|
|
5566
|
+
"agents.defaults.maxToolIterations": "Maximum tool calls per turn.",
|
|
5567
|
+
"agents.context.bootstrap.files": "Files injected into the system prompt at startup.",
|
|
5568
|
+
"agents.context.bootstrap.minimalFiles": "Minimal file set used for low-context runs.",
|
|
5569
|
+
"agents.context.bootstrap.heartbeatFiles": "Files checked periodically for tasks.",
|
|
5570
|
+
"agents.context.bootstrap.perFileChars": "Max chars per bootstrap file.",
|
|
5571
|
+
"agents.context.bootstrap.totalChars": "Max total chars across bootstrap files.",
|
|
5572
|
+
"agents.context.memory.enabled": "Enable memory injection from memory files.",
|
|
5573
|
+
"agents.context.memory.maxChars": "Max characters of memory injected per turn.",
|
|
5574
|
+
"providers.*.apiKey": "API key for this provider.",
|
|
5575
|
+
"providers.*.apiBase": "Override the provider API base URL if needed.",
|
|
5576
|
+
"providers.*.extraHeaders": "Extra headers to send to the provider.",
|
|
5577
|
+
"providers.*.wireApi": "Select API mode (auto/chat/responses) for providers that support it.",
|
|
5578
|
+
"gateway.host": "Bind address for the gateway server.",
|
|
5579
|
+
"gateway.port": "Port for the gateway server.",
|
|
5580
|
+
"ui.enabled": "Enable the built-in UI server.",
|
|
5581
|
+
"ui.host": "Bind address for the UI server.",
|
|
5582
|
+
"ui.port": "Port for the UI server.",
|
|
5583
|
+
"ui.open": "Open the browser when UI starts.",
|
|
5584
|
+
"tools.web.search.apiKey": "API key for the configured web search provider.",
|
|
5585
|
+
"tools.web.search.maxResults": "Default number of search results.",
|
|
5586
|
+
"tools.exec.timeout": "Command execution timeout (seconds).",
|
|
5587
|
+
"tools.restrictToWorkspace": "Restrict tools to the workspace directory.",
|
|
5588
|
+
"channels.whatsapp.bridgeUrl": "WebSocket URL for the WhatsApp bridge.",
|
|
5589
|
+
"channels.telegram.token": "Telegram bot token.",
|
|
5590
|
+
"channels.telegram.proxy": "Optional HTTP proxy for Telegram.",
|
|
5591
|
+
"channels.discord.token": "Discord bot token.",
|
|
5592
|
+
"channels.discord.gatewayUrl": "Override Discord gateway URL.",
|
|
5593
|
+
"channels.discord.intents": "Gateway intents bitmask.",
|
|
5594
|
+
"channels.feishu.appId": "Feishu app ID.",
|
|
5595
|
+
"channels.feishu.appSecret": "Feishu app secret.",
|
|
5596
|
+
"channels.feishu.encryptKey": "Feishu encrypt key (if enabled).",
|
|
5597
|
+
"channels.feishu.verificationToken": "Feishu verification token.",
|
|
5598
|
+
"channels.dingtalk.clientId": "DingTalk client ID.",
|
|
5599
|
+
"channels.dingtalk.clientSecret": "DingTalk client secret.",
|
|
5600
|
+
"channels.mochat.baseUrl": "Base URL for Mochat API.",
|
|
5601
|
+
"channels.mochat.socketUrl": "WebSocket URL for Mochat (optional override).",
|
|
5602
|
+
"channels.mochat.socketPath": "Socket.IO path for Mochat.",
|
|
5603
|
+
"channels.mochat.clawToken": "Mochat claw token.",
|
|
5604
|
+
"channels.mochat.agentUserId": "Mochat agent user id.",
|
|
5605
|
+
"channels.mochat.replyDelayMode": "Reply delay policy for Mochat.",
|
|
5606
|
+
"channels.mochat.replyDelayMs": "Reply delay duration in milliseconds.",
|
|
5607
|
+
"channels.slack.mode": "Slack connection mode (socket or webhook).",
|
|
5608
|
+
"channels.slack.webhookPath": "Slack webhook path when using webhook mode.",
|
|
5609
|
+
"channels.slack.botToken": "Slack bot token.",
|
|
5610
|
+
"channels.slack.appToken": "Slack app-level token.",
|
|
5611
|
+
"channels.slack.groupPolicy": "Group policy for Slack channels.",
|
|
5612
|
+
"channels.slack.dm.policy": "DM policy for Slack.",
|
|
5613
|
+
"channels.email.imapHost": "IMAP server host.",
|
|
5614
|
+
"channels.email.imapPort": "IMAP server port.",
|
|
5615
|
+
"channels.email.imapUsername": "IMAP username.",
|
|
5616
|
+
"channels.email.imapPassword": "IMAP password.",
|
|
5617
|
+
"channels.email.smtpHost": "SMTP server host.",
|
|
5618
|
+
"channels.email.smtpPort": "SMTP server port.",
|
|
5619
|
+
"channels.email.smtpUsername": "SMTP username.",
|
|
5620
|
+
"channels.email.smtpPassword": "SMTP password.",
|
|
5621
|
+
"channels.email.fromAddress": "Default From address for outgoing mail.",
|
|
5622
|
+
"channels.email.pollIntervalSeconds": "Polling interval in seconds.",
|
|
5623
|
+
"channels.email.maxBodyChars": "Max chars to read from incoming emails.",
|
|
5624
|
+
"channels.email.subjectPrefix": "Prefix used for reply subjects.",
|
|
5625
|
+
"channels.qq.appId": "QQ app ID.",
|
|
5626
|
+
"channels.qq.secret": "QQ app secret."
|
|
5627
|
+
};
|
|
5628
|
+
|
|
5629
|
+
// src/config/schema.labels.ts
|
|
5630
|
+
var FIELD_LABELS = {
|
|
5631
|
+
agents: "Agents",
|
|
5632
|
+
"agents.defaults": "Agent Defaults",
|
|
5633
|
+
"agents.defaults.workspace": "Workspace",
|
|
5634
|
+
"agents.defaults.model": "Default Model",
|
|
5635
|
+
"agents.defaults.maxTokens": "Max Tokens",
|
|
5636
|
+
"agents.defaults.temperature": "Temperature",
|
|
5637
|
+
"agents.defaults.maxToolIterations": "Max Tool Iterations",
|
|
5638
|
+
"agents.context": "Context",
|
|
5639
|
+
"agents.context.bootstrap": "Bootstrap Files",
|
|
5640
|
+
"agents.context.bootstrap.files": "Bootstrap Files",
|
|
5641
|
+
"agents.context.bootstrap.minimalFiles": "Minimal Files",
|
|
5642
|
+
"agents.context.bootstrap.heartbeatFiles": "Heartbeat Files",
|
|
5643
|
+
"agents.context.bootstrap.perFileChars": "Max Chars per File",
|
|
5644
|
+
"agents.context.bootstrap.totalChars": "Total Bootstrap Chars",
|
|
5645
|
+
"agents.context.memory": "Memory",
|
|
5646
|
+
"agents.context.memory.enabled": "Enable Memory",
|
|
5647
|
+
"agents.context.memory.maxChars": "Max Memory Chars",
|
|
5648
|
+
providers: "Providers",
|
|
5649
|
+
"providers.*.apiKey": "API Key",
|
|
5650
|
+
"providers.*.apiBase": "API Base URL",
|
|
5651
|
+
"providers.*.extraHeaders": "Extra Headers",
|
|
5652
|
+
"providers.*.wireApi": "Wire API Mode",
|
|
5653
|
+
channels: "Channels",
|
|
5654
|
+
gateway: "Gateway",
|
|
5655
|
+
"gateway.host": "Gateway Host",
|
|
5656
|
+
"gateway.port": "Gateway Port",
|
|
5657
|
+
ui: "UI",
|
|
5658
|
+
"ui.enabled": "Enable UI",
|
|
5659
|
+
"ui.host": "UI Host",
|
|
5660
|
+
"ui.port": "UI Port",
|
|
5661
|
+
"ui.open": "Open Browser",
|
|
5662
|
+
tools: "Tools",
|
|
5663
|
+
"tools.web": "Web Tools",
|
|
5664
|
+
"tools.web.search": "Web Search",
|
|
5665
|
+
"tools.web.search.apiKey": "Search API Key",
|
|
5666
|
+
"tools.web.search.maxResults": "Max Results",
|
|
5667
|
+
"tools.exec": "Command Execution",
|
|
5668
|
+
"tools.exec.timeout": "Exec Timeout (seconds)",
|
|
5669
|
+
"tools.restrictToWorkspace": "Restrict Tools to Workspace",
|
|
5670
|
+
"channels.whatsapp": "WhatsApp",
|
|
5671
|
+
"channels.whatsapp.enabled": "Enabled",
|
|
5672
|
+
"channels.whatsapp.bridgeUrl": "Bridge URL",
|
|
5673
|
+
"channels.whatsapp.allowFrom": "Allow From",
|
|
5674
|
+
"channels.telegram": "Telegram",
|
|
5675
|
+
"channels.telegram.enabled": "Enabled",
|
|
5676
|
+
"channels.telegram.token": "Bot Token",
|
|
5677
|
+
"channels.telegram.allowFrom": "Allow From",
|
|
5678
|
+
"channels.telegram.proxy": "Proxy",
|
|
5679
|
+
"channels.discord": "Discord",
|
|
5680
|
+
"channels.discord.enabled": "Enabled",
|
|
5681
|
+
"channels.discord.token": "Bot Token",
|
|
5682
|
+
"channels.discord.allowFrom": "Allow From",
|
|
5683
|
+
"channels.discord.gatewayUrl": "Gateway URL",
|
|
5684
|
+
"channels.discord.intents": "Gateway Intents",
|
|
5685
|
+
"channels.feishu": "Feishu",
|
|
5686
|
+
"channels.feishu.enabled": "Enabled",
|
|
5687
|
+
"channels.feishu.appId": "App ID",
|
|
5688
|
+
"channels.feishu.appSecret": "App Secret",
|
|
5689
|
+
"channels.feishu.encryptKey": "Encrypt Key",
|
|
5690
|
+
"channels.feishu.verificationToken": "Verification Token",
|
|
5691
|
+
"channels.feishu.allowFrom": "Allow From",
|
|
5692
|
+
"channels.dingtalk": "DingTalk",
|
|
5693
|
+
"channels.dingtalk.enabled": "Enabled",
|
|
5694
|
+
"channels.dingtalk.clientId": "Client ID",
|
|
5695
|
+
"channels.dingtalk.clientSecret": "Client Secret",
|
|
5696
|
+
"channels.dingtalk.allowFrom": "Allow From",
|
|
5697
|
+
"channels.mochat": "Mochat",
|
|
5698
|
+
"channels.mochat.enabled": "Enabled",
|
|
5699
|
+
"channels.mochat.baseUrl": "Base URL",
|
|
5700
|
+
"channels.mochat.socketUrl": "Socket URL",
|
|
5701
|
+
"channels.mochat.socketPath": "Socket Path",
|
|
5702
|
+
"channels.mochat.clawToken": "Claw Token",
|
|
5703
|
+
"channels.mochat.agentUserId": "Agent User ID",
|
|
5704
|
+
"channels.mochat.allowFrom": "Allow From",
|
|
5705
|
+
"channels.mochat.replyDelayMode": "Reply Delay Mode",
|
|
5706
|
+
"channels.mochat.replyDelayMs": "Reply Delay (ms)",
|
|
5707
|
+
"channels.slack": "Slack",
|
|
5708
|
+
"channels.slack.enabled": "Enabled",
|
|
5709
|
+
"channels.slack.mode": "Mode",
|
|
5710
|
+
"channels.slack.webhookPath": "Webhook Path",
|
|
5711
|
+
"channels.slack.botToken": "Bot Token",
|
|
5712
|
+
"channels.slack.appToken": "App Token",
|
|
5713
|
+
"channels.slack.userTokenReadOnly": "User Token Read Only",
|
|
5714
|
+
"channels.slack.groupPolicy": "Group Policy",
|
|
5715
|
+
"channels.slack.groupAllowFrom": "Group Allow From",
|
|
5716
|
+
"channels.slack.dm": "DM",
|
|
5717
|
+
"channels.slack.dm.enabled": "Enabled",
|
|
5718
|
+
"channels.slack.dm.policy": "DM Policy",
|
|
5719
|
+
"channels.slack.dm.allowFrom": "Allow From",
|
|
5720
|
+
"channels.email": "Email",
|
|
5721
|
+
"channels.email.enabled": "Enabled",
|
|
5722
|
+
"channels.email.imapHost": "IMAP Host",
|
|
5723
|
+
"channels.email.imapPort": "IMAP Port",
|
|
5724
|
+
"channels.email.imapUsername": "IMAP Username",
|
|
5725
|
+
"channels.email.imapPassword": "IMAP Password",
|
|
5726
|
+
"channels.email.smtpHost": "SMTP Host",
|
|
5727
|
+
"channels.email.smtpPort": "SMTP Port",
|
|
5728
|
+
"channels.email.smtpUsername": "SMTP Username",
|
|
5729
|
+
"channels.email.smtpPassword": "SMTP Password",
|
|
5730
|
+
"channels.email.fromAddress": "From Address",
|
|
5731
|
+
"channels.email.pollIntervalSeconds": "Poll Interval (seconds)",
|
|
5732
|
+
"channels.email.maxBodyChars": "Max Body Chars",
|
|
5733
|
+
"channels.email.subjectPrefix": "Subject Prefix",
|
|
5734
|
+
"channels.email.allowFrom": "Allow From",
|
|
5735
|
+
"channels.qq": "QQ",
|
|
5736
|
+
"channels.qq.enabled": "Enabled",
|
|
5737
|
+
"channels.qq.appId": "App ID",
|
|
5738
|
+
"channels.qq.secret": "App Secret",
|
|
5739
|
+
"channels.qq.markdownSupport": "Markdown Support",
|
|
5740
|
+
"channels.qq.allowFrom": "Allow From"
|
|
5741
|
+
};
|
|
5742
|
+
|
|
5743
|
+
// src/config/schema.hints.ts
|
|
5744
|
+
var GROUP_LABELS = {
|
|
5745
|
+
agents: "Agents",
|
|
5746
|
+
providers: "Providers",
|
|
5747
|
+
channels: "Channels",
|
|
5748
|
+
tools: "Tools",
|
|
5749
|
+
gateway: "Gateway",
|
|
5750
|
+
ui: "UI"
|
|
5751
|
+
};
|
|
5752
|
+
var GROUP_ORDER = {
|
|
5753
|
+
agents: 20,
|
|
5754
|
+
providers: 30,
|
|
5755
|
+
channels: 40,
|
|
5756
|
+
tools: 50,
|
|
5757
|
+
gateway: 60,
|
|
5758
|
+
ui: 70
|
|
5759
|
+
};
|
|
5760
|
+
var FIELD_PLACEHOLDERS = {
|
|
5761
|
+
"gateway.host": "0.0.0.0",
|
|
5762
|
+
"gateway.port": "18790",
|
|
5763
|
+
"ui.host": "127.0.0.1",
|
|
5764
|
+
"ui.port": "18791",
|
|
5765
|
+
"providers.*.apiBase": "https://api.example.com"
|
|
5766
|
+
};
|
|
5767
|
+
var SENSITIVE_KEY_WHITELIST_SUFFIXES = [
|
|
5768
|
+
"maxtokens",
|
|
5769
|
+
"maxoutputtokens",
|
|
5770
|
+
"maxinputtokens",
|
|
5771
|
+
"maxcompletiontokens",
|
|
5772
|
+
"contexttokens",
|
|
5773
|
+
"totaltokens",
|
|
5774
|
+
"tokencount",
|
|
5775
|
+
"tokenlimit",
|
|
5776
|
+
"tokenbudget"
|
|
5777
|
+
];
|
|
5778
|
+
var NORMALIZED_SENSITIVE_KEY_WHITELIST_SUFFIXES = SENSITIVE_KEY_WHITELIST_SUFFIXES.map(
|
|
5779
|
+
(suffix) => suffix.toLowerCase()
|
|
5780
|
+
);
|
|
5781
|
+
var SENSITIVE_PATTERNS = [/token$/i, /password/i, /secret/i, /api.?key/i];
|
|
5782
|
+
function isWhitelistedSensitivePath(path) {
|
|
5783
|
+
const lowerPath = path.toLowerCase();
|
|
5784
|
+
return NORMALIZED_SENSITIVE_KEY_WHITELIST_SUFFIXES.some((suffix) => lowerPath.endsWith(suffix));
|
|
5785
|
+
}
|
|
5786
|
+
function matchesSensitivePattern(path) {
|
|
5787
|
+
return SENSITIVE_PATTERNS.some((pattern) => pattern.test(path));
|
|
5788
|
+
}
|
|
5789
|
+
function isSensitiveConfigPath(path) {
|
|
5790
|
+
return !isWhitelistedSensitivePath(path) && matchesSensitivePattern(path);
|
|
5791
|
+
}
|
|
5792
|
+
function buildBaseHints() {
|
|
5793
|
+
const hints = {};
|
|
5794
|
+
for (const [group, label] of Object.entries(GROUP_LABELS)) {
|
|
5795
|
+
hints[group] = {
|
|
5796
|
+
label,
|
|
5797
|
+
group: label,
|
|
5798
|
+
order: GROUP_ORDER[group]
|
|
5799
|
+
};
|
|
5800
|
+
}
|
|
5801
|
+
for (const [path, label] of Object.entries(FIELD_LABELS)) {
|
|
5802
|
+
const current = hints[path];
|
|
5803
|
+
hints[path] = current ? { ...current, label } : { label };
|
|
5804
|
+
}
|
|
5805
|
+
for (const [path, help] of Object.entries(FIELD_HELP)) {
|
|
5806
|
+
const current = hints[path];
|
|
5807
|
+
hints[path] = current ? { ...current, help } : { help };
|
|
5808
|
+
}
|
|
5809
|
+
for (const [path, placeholder] of Object.entries(FIELD_PLACEHOLDERS)) {
|
|
5810
|
+
const current = hints[path];
|
|
5811
|
+
hints[path] = current ? { ...current, placeholder } : { placeholder };
|
|
5812
|
+
}
|
|
5813
|
+
return hints;
|
|
5814
|
+
}
|
|
5815
|
+
function applySensitiveHints(hints) {
|
|
5816
|
+
const next = { ...hints };
|
|
5817
|
+
for (const key of Object.keys(next)) {
|
|
5818
|
+
if (next[key]?.sensitive !== void 0) {
|
|
5819
|
+
continue;
|
|
5820
|
+
}
|
|
5821
|
+
if (isSensitiveConfigPath(key)) {
|
|
5822
|
+
next[key] = { ...next[key], sensitive: true };
|
|
5823
|
+
}
|
|
5824
|
+
}
|
|
5825
|
+
return next;
|
|
5826
|
+
}
|
|
5827
|
+
function isUnwrappable(object) {
|
|
5828
|
+
return !!object && typeof object === "object" && "unwrap" in object && typeof object.unwrap === "function" && !(object instanceof z.ZodArray);
|
|
5829
|
+
}
|
|
5830
|
+
function mapSensitivePaths(schema, path, hints) {
|
|
5831
|
+
let next = { ...hints };
|
|
5832
|
+
let currentSchema = schema;
|
|
5833
|
+
while (isUnwrappable(currentSchema)) {
|
|
5834
|
+
currentSchema = currentSchema.unwrap();
|
|
5835
|
+
}
|
|
5836
|
+
if (path && isSensitiveConfigPath(path) && !next[path]?.sensitive) {
|
|
5837
|
+
next[path] = { ...next[path], sensitive: true };
|
|
5838
|
+
}
|
|
5839
|
+
if (currentSchema instanceof z.ZodObject) {
|
|
5840
|
+
const shape = currentSchema.shape;
|
|
5841
|
+
for (const key in shape) {
|
|
5842
|
+
const nextPath = path ? `${path}.${key}` : key;
|
|
5843
|
+
next = mapSensitivePaths(shape[key], nextPath, next);
|
|
5844
|
+
}
|
|
5845
|
+
} else if (currentSchema instanceof z.ZodArray) {
|
|
5846
|
+
const nextPath = path ? `${path}[]` : "[]";
|
|
5847
|
+
next = mapSensitivePaths(currentSchema.element, nextPath, next);
|
|
5848
|
+
} else if (currentSchema instanceof z.ZodRecord) {
|
|
5849
|
+
const nextPath = path ? `${path}.*` : "*";
|
|
5850
|
+
next = mapSensitivePaths(currentSchema._def.valueType, nextPath, next);
|
|
5851
|
+
} else if (currentSchema instanceof z.ZodUnion || currentSchema instanceof z.ZodDiscriminatedUnion) {
|
|
5852
|
+
for (const option of currentSchema.options) {
|
|
5853
|
+
next = mapSensitivePaths(option, path, next);
|
|
5854
|
+
}
|
|
5855
|
+
}
|
|
5856
|
+
return next;
|
|
5857
|
+
}
|
|
5858
|
+
|
|
5520
5859
|
// src/config/schema.ts
|
|
5521
|
-
var allowFrom =
|
|
5522
|
-
var WhatsAppConfigSchema =
|
|
5523
|
-
enabled:
|
|
5524
|
-
bridgeUrl:
|
|
5860
|
+
var allowFrom = z2.array(z2.string()).default([]);
|
|
5861
|
+
var WhatsAppConfigSchema = z2.object({
|
|
5862
|
+
enabled: z2.boolean().default(false),
|
|
5863
|
+
bridgeUrl: z2.string().default("ws://localhost:3001"),
|
|
5525
5864
|
allowFrom
|
|
5526
5865
|
});
|
|
5527
|
-
var TelegramConfigSchema =
|
|
5528
|
-
enabled:
|
|
5529
|
-
token:
|
|
5866
|
+
var TelegramConfigSchema = z2.object({
|
|
5867
|
+
enabled: z2.boolean().default(false),
|
|
5868
|
+
token: z2.string().default(""),
|
|
5530
5869
|
allowFrom,
|
|
5531
|
-
proxy:
|
|
5870
|
+
proxy: z2.string().nullable().default(null)
|
|
5532
5871
|
});
|
|
5533
|
-
var FeishuConfigSchema =
|
|
5534
|
-
enabled:
|
|
5535
|
-
appId:
|
|
5536
|
-
appSecret:
|
|
5537
|
-
encryptKey:
|
|
5538
|
-
verificationToken:
|
|
5872
|
+
var FeishuConfigSchema = z2.object({
|
|
5873
|
+
enabled: z2.boolean().default(false),
|
|
5874
|
+
appId: z2.string().default(""),
|
|
5875
|
+
appSecret: z2.string().default(""),
|
|
5876
|
+
encryptKey: z2.string().default(""),
|
|
5877
|
+
verificationToken: z2.string().default(""),
|
|
5539
5878
|
allowFrom
|
|
5540
5879
|
});
|
|
5541
|
-
var DingTalkConfigSchema =
|
|
5542
|
-
enabled:
|
|
5543
|
-
clientId:
|
|
5544
|
-
clientSecret:
|
|
5880
|
+
var DingTalkConfigSchema = z2.object({
|
|
5881
|
+
enabled: z2.boolean().default(false),
|
|
5882
|
+
clientId: z2.string().default(""),
|
|
5883
|
+
clientSecret: z2.string().default(""),
|
|
5545
5884
|
allowFrom
|
|
5546
5885
|
});
|
|
5547
|
-
var DiscordConfigSchema =
|
|
5548
|
-
enabled:
|
|
5549
|
-
token:
|
|
5886
|
+
var DiscordConfigSchema = z2.object({
|
|
5887
|
+
enabled: z2.boolean().default(false),
|
|
5888
|
+
token: z2.string().default(""),
|
|
5550
5889
|
allowFrom,
|
|
5551
|
-
gatewayUrl:
|
|
5552
|
-
intents:
|
|
5890
|
+
gatewayUrl: z2.string().default("wss://gateway.discord.gg/?v=10&encoding=json"),
|
|
5891
|
+
intents: z2.number().int().default(37377)
|
|
5553
5892
|
});
|
|
5554
|
-
var EmailConfigSchema =
|
|
5555
|
-
enabled:
|
|
5556
|
-
consentGranted:
|
|
5557
|
-
imapHost:
|
|
5558
|
-
imapPort:
|
|
5559
|
-
imapUsername:
|
|
5560
|
-
imapPassword:
|
|
5561
|
-
imapMailbox:
|
|
5562
|
-
imapUseSsl:
|
|
5563
|
-
smtpHost:
|
|
5564
|
-
smtpPort:
|
|
5565
|
-
smtpUsername:
|
|
5566
|
-
smtpPassword:
|
|
5567
|
-
smtpUseTls:
|
|
5568
|
-
smtpUseSsl:
|
|
5569
|
-
fromAddress:
|
|
5570
|
-
autoReplyEnabled:
|
|
5571
|
-
pollIntervalSeconds:
|
|
5572
|
-
markSeen:
|
|
5573
|
-
maxBodyChars:
|
|
5574
|
-
subjectPrefix:
|
|
5893
|
+
var EmailConfigSchema = z2.object({
|
|
5894
|
+
enabled: z2.boolean().default(false),
|
|
5895
|
+
consentGranted: z2.boolean().default(false),
|
|
5896
|
+
imapHost: z2.string().default(""),
|
|
5897
|
+
imapPort: z2.number().int().default(993),
|
|
5898
|
+
imapUsername: z2.string().default(""),
|
|
5899
|
+
imapPassword: z2.string().default(""),
|
|
5900
|
+
imapMailbox: z2.string().default("INBOX"),
|
|
5901
|
+
imapUseSsl: z2.boolean().default(true),
|
|
5902
|
+
smtpHost: z2.string().default(""),
|
|
5903
|
+
smtpPort: z2.number().int().default(587),
|
|
5904
|
+
smtpUsername: z2.string().default(""),
|
|
5905
|
+
smtpPassword: z2.string().default(""),
|
|
5906
|
+
smtpUseTls: z2.boolean().default(true),
|
|
5907
|
+
smtpUseSsl: z2.boolean().default(false),
|
|
5908
|
+
fromAddress: z2.string().default(""),
|
|
5909
|
+
autoReplyEnabled: z2.boolean().default(true),
|
|
5910
|
+
pollIntervalSeconds: z2.number().int().default(30),
|
|
5911
|
+
markSeen: z2.boolean().default(true),
|
|
5912
|
+
maxBodyChars: z2.number().int().default(12e3),
|
|
5913
|
+
subjectPrefix: z2.string().default("Re: "),
|
|
5575
5914
|
allowFrom
|
|
5576
5915
|
});
|
|
5577
|
-
var MochatMentionSchema =
|
|
5578
|
-
requireInGroups:
|
|
5916
|
+
var MochatMentionSchema = z2.object({
|
|
5917
|
+
requireInGroups: z2.boolean().default(false)
|
|
5579
5918
|
});
|
|
5580
|
-
var MochatGroupRuleSchema =
|
|
5581
|
-
requireMention:
|
|
5919
|
+
var MochatGroupRuleSchema = z2.object({
|
|
5920
|
+
requireMention: z2.boolean().default(false)
|
|
5582
5921
|
});
|
|
5583
|
-
var MochatConfigSchema =
|
|
5584
|
-
enabled:
|
|
5585
|
-
baseUrl:
|
|
5586
|
-
socketUrl:
|
|
5587
|
-
socketPath:
|
|
5588
|
-
socketDisableMsgpack:
|
|
5589
|
-
socketReconnectDelayMs:
|
|
5590
|
-
socketMaxReconnectDelayMs:
|
|
5591
|
-
socketConnectTimeoutMs:
|
|
5592
|
-
refreshIntervalMs:
|
|
5593
|
-
watchTimeoutMs:
|
|
5594
|
-
watchLimit:
|
|
5595
|
-
retryDelayMs:
|
|
5596
|
-
maxRetryAttempts:
|
|
5597
|
-
clawToken:
|
|
5598
|
-
agentUserId:
|
|
5599
|
-
sessions:
|
|
5600
|
-
panels:
|
|
5922
|
+
var MochatConfigSchema = z2.object({
|
|
5923
|
+
enabled: z2.boolean().default(false),
|
|
5924
|
+
baseUrl: z2.string().default("https://mochat.io"),
|
|
5925
|
+
socketUrl: z2.string().default(""),
|
|
5926
|
+
socketPath: z2.string().default("/socket.io"),
|
|
5927
|
+
socketDisableMsgpack: z2.boolean().default(false),
|
|
5928
|
+
socketReconnectDelayMs: z2.number().int().default(1e3),
|
|
5929
|
+
socketMaxReconnectDelayMs: z2.number().int().default(1e4),
|
|
5930
|
+
socketConnectTimeoutMs: z2.number().int().default(1e4),
|
|
5931
|
+
refreshIntervalMs: z2.number().int().default(3e4),
|
|
5932
|
+
watchTimeoutMs: z2.number().int().default(25e3),
|
|
5933
|
+
watchLimit: z2.number().int().default(100),
|
|
5934
|
+
retryDelayMs: z2.number().int().default(500),
|
|
5935
|
+
maxRetryAttempts: z2.number().int().default(0),
|
|
5936
|
+
clawToken: z2.string().default(""),
|
|
5937
|
+
agentUserId: z2.string().default(""),
|
|
5938
|
+
sessions: z2.array(z2.string()).default([]),
|
|
5939
|
+
panels: z2.array(z2.string()).default([]),
|
|
5601
5940
|
allowFrom,
|
|
5602
5941
|
mention: MochatMentionSchema.default({}),
|
|
5603
|
-
groups:
|
|
5604
|
-
replyDelayMode:
|
|
5605
|
-
replyDelayMs:
|
|
5942
|
+
groups: z2.record(MochatGroupRuleSchema).default({}),
|
|
5943
|
+
replyDelayMode: z2.string().default("non-mention"),
|
|
5944
|
+
replyDelayMs: z2.number().int().default(12e4)
|
|
5606
5945
|
});
|
|
5607
|
-
var SlackDMSchema =
|
|
5608
|
-
enabled:
|
|
5609
|
-
policy:
|
|
5946
|
+
var SlackDMSchema = z2.object({
|
|
5947
|
+
enabled: z2.boolean().default(true),
|
|
5948
|
+
policy: z2.string().default("open"),
|
|
5610
5949
|
allowFrom
|
|
5611
5950
|
});
|
|
5612
|
-
var SlackConfigSchema =
|
|
5613
|
-
enabled:
|
|
5614
|
-
mode:
|
|
5615
|
-
webhookPath:
|
|
5616
|
-
botToken:
|
|
5617
|
-
appToken:
|
|
5618
|
-
userTokenReadOnly:
|
|
5619
|
-
groupPolicy:
|
|
5951
|
+
var SlackConfigSchema = z2.object({
|
|
5952
|
+
enabled: z2.boolean().default(false),
|
|
5953
|
+
mode: z2.string().default("socket"),
|
|
5954
|
+
webhookPath: z2.string().default("/slack/events"),
|
|
5955
|
+
botToken: z2.string().default(""),
|
|
5956
|
+
appToken: z2.string().default(""),
|
|
5957
|
+
userTokenReadOnly: z2.boolean().default(true),
|
|
5958
|
+
groupPolicy: z2.string().default("mention"),
|
|
5620
5959
|
groupAllowFrom: allowFrom,
|
|
5621
5960
|
dm: SlackDMSchema.default({})
|
|
5622
5961
|
});
|
|
5623
|
-
var QQConfigSchema =
|
|
5624
|
-
enabled:
|
|
5625
|
-
appId:
|
|
5626
|
-
secret:
|
|
5627
|
-
markdownSupport:
|
|
5962
|
+
var QQConfigSchema = z2.object({
|
|
5963
|
+
enabled: z2.boolean().default(false),
|
|
5964
|
+
appId: z2.string().default(""),
|
|
5965
|
+
secret: z2.string().default(""),
|
|
5966
|
+
markdownSupport: z2.boolean().default(false),
|
|
5628
5967
|
allowFrom
|
|
5629
5968
|
});
|
|
5630
|
-
var ChannelsConfigSchema =
|
|
5969
|
+
var ChannelsConfigSchema = z2.object({
|
|
5631
5970
|
whatsapp: WhatsAppConfigSchema.default({}),
|
|
5632
5971
|
telegram: TelegramConfigSchema.default({}),
|
|
5633
5972
|
discord: DiscordConfigSchema.default({}),
|
|
@@ -5638,15 +5977,15 @@ var ChannelsConfigSchema = z.object({
|
|
|
5638
5977
|
slack: SlackConfigSchema.default({}),
|
|
5639
5978
|
qq: QQConfigSchema.default({})
|
|
5640
5979
|
});
|
|
5641
|
-
var AgentDefaultsSchema =
|
|
5642
|
-
workspace:
|
|
5643
|
-
model:
|
|
5644
|
-
maxTokens:
|
|
5645
|
-
temperature:
|
|
5646
|
-
maxToolIterations:
|
|
5980
|
+
var AgentDefaultsSchema = z2.object({
|
|
5981
|
+
workspace: z2.string().default(DEFAULT_WORKSPACE_PATH),
|
|
5982
|
+
model: z2.string().default("anthropic/claude-opus-4-5"),
|
|
5983
|
+
maxTokens: z2.number().int().default(8192),
|
|
5984
|
+
temperature: z2.number().default(0.7),
|
|
5985
|
+
maxToolIterations: z2.number().int().default(20)
|
|
5647
5986
|
});
|
|
5648
|
-
var ContextBootstrapSchema =
|
|
5649
|
-
files:
|
|
5987
|
+
var ContextBootstrapSchema = z2.object({
|
|
5988
|
+
files: z2.array(z2.string()).default([
|
|
5650
5989
|
"AGENTS.md",
|
|
5651
5990
|
"SOUL.md",
|
|
5652
5991
|
"USER.md",
|
|
@@ -5656,30 +5995,30 @@ var ContextBootstrapSchema = z.object({
|
|
|
5656
5995
|
"BOOTSTRAP.md",
|
|
5657
5996
|
"HEARTBEAT.md"
|
|
5658
5997
|
]),
|
|
5659
|
-
minimalFiles:
|
|
5660
|
-
heartbeatFiles:
|
|
5661
|
-
perFileChars:
|
|
5662
|
-
totalChars:
|
|
5998
|
+
minimalFiles: z2.array(z2.string()).default(["AGENTS.md", "SOUL.md", "TOOLS.md", "IDENTITY.md"]),
|
|
5999
|
+
heartbeatFiles: z2.array(z2.string()).default(["HEARTBEAT.md"]),
|
|
6000
|
+
perFileChars: z2.number().int().default(4e3),
|
|
6001
|
+
totalChars: z2.number().int().default(12e3)
|
|
5663
6002
|
});
|
|
5664
|
-
var ContextMemorySchema =
|
|
5665
|
-
enabled:
|
|
5666
|
-
maxChars:
|
|
6003
|
+
var ContextMemorySchema = z2.object({
|
|
6004
|
+
enabled: z2.boolean().default(true),
|
|
6005
|
+
maxChars: z2.number().int().default(8e3)
|
|
5667
6006
|
});
|
|
5668
|
-
var ContextConfigSchema =
|
|
6007
|
+
var ContextConfigSchema = z2.object({
|
|
5669
6008
|
bootstrap: ContextBootstrapSchema.default({}),
|
|
5670
6009
|
memory: ContextMemorySchema.default({})
|
|
5671
6010
|
});
|
|
5672
|
-
var AgentsConfigSchema =
|
|
6011
|
+
var AgentsConfigSchema = z2.object({
|
|
5673
6012
|
defaults: AgentDefaultsSchema.default({}),
|
|
5674
6013
|
context: ContextConfigSchema.default({})
|
|
5675
6014
|
});
|
|
5676
|
-
var ProviderConfigSchema =
|
|
5677
|
-
apiKey:
|
|
5678
|
-
apiBase:
|
|
5679
|
-
extraHeaders:
|
|
5680
|
-
wireApi:
|
|
6015
|
+
var ProviderConfigSchema = z2.object({
|
|
6016
|
+
apiKey: z2.string().default(""),
|
|
6017
|
+
apiBase: z2.string().nullable().default(null),
|
|
6018
|
+
extraHeaders: z2.record(z2.string()).nullable().default(null),
|
|
6019
|
+
wireApi: z2.enum(["auto", "chat", "responses"]).default("auto")
|
|
5681
6020
|
});
|
|
5682
|
-
var ProvidersConfigSchema =
|
|
6021
|
+
var ProvidersConfigSchema = z2.object({
|
|
5683
6022
|
anthropic: ProviderConfigSchema.default({}),
|
|
5684
6023
|
openai: ProviderConfigSchema.default({}),
|
|
5685
6024
|
openrouter: ProviderConfigSchema.default({}),
|
|
@@ -5693,32 +6032,32 @@ var ProvidersConfigSchema = z.object({
|
|
|
5693
6032
|
minimax: ProviderConfigSchema.default({}),
|
|
5694
6033
|
aihubmix: ProviderConfigSchema.default({})
|
|
5695
6034
|
});
|
|
5696
|
-
var GatewayConfigSchema =
|
|
5697
|
-
host:
|
|
5698
|
-
port:
|
|
6035
|
+
var GatewayConfigSchema = z2.object({
|
|
6036
|
+
host: z2.string().default("0.0.0.0"),
|
|
6037
|
+
port: z2.number().int().default(18790)
|
|
5699
6038
|
});
|
|
5700
|
-
var UiConfigSchema =
|
|
5701
|
-
enabled:
|
|
5702
|
-
host:
|
|
5703
|
-
port:
|
|
5704
|
-
open:
|
|
6039
|
+
var UiConfigSchema = z2.object({
|
|
6040
|
+
enabled: z2.boolean().default(false),
|
|
6041
|
+
host: z2.string().default("127.0.0.1"),
|
|
6042
|
+
port: z2.number().int().default(18791),
|
|
6043
|
+
open: z2.boolean().default(false)
|
|
5705
6044
|
});
|
|
5706
|
-
var WebSearchConfigSchema =
|
|
5707
|
-
apiKey:
|
|
5708
|
-
maxResults:
|
|
6045
|
+
var WebSearchConfigSchema = z2.object({
|
|
6046
|
+
apiKey: z2.string().default(""),
|
|
6047
|
+
maxResults: z2.number().int().default(5)
|
|
5709
6048
|
});
|
|
5710
|
-
var WebToolsConfigSchema =
|
|
6049
|
+
var WebToolsConfigSchema = z2.object({
|
|
5711
6050
|
search: WebSearchConfigSchema.default({})
|
|
5712
6051
|
});
|
|
5713
|
-
var ExecToolConfigSchema =
|
|
5714
|
-
timeout:
|
|
6052
|
+
var ExecToolConfigSchema = z2.object({
|
|
6053
|
+
timeout: z2.number().int().default(60)
|
|
5715
6054
|
});
|
|
5716
|
-
var ToolsConfigSchema =
|
|
6055
|
+
var ToolsConfigSchema = z2.object({
|
|
5717
6056
|
web: WebToolsConfigSchema.default({}),
|
|
5718
6057
|
exec: ExecToolConfigSchema.default({}),
|
|
5719
|
-
restrictToWorkspace:
|
|
6058
|
+
restrictToWorkspace: z2.boolean().default(false)
|
|
5720
6059
|
});
|
|
5721
|
-
var ConfigSchema =
|
|
6060
|
+
var ConfigSchema = z2.object({
|
|
5722
6061
|
agents: AgentsConfigSchema.default({}),
|
|
5723
6062
|
channels: ChannelsConfigSchema.default({}),
|
|
5724
6063
|
providers: ProvidersConfigSchema.default({}),
|
|
@@ -5768,6 +6107,22 @@ function getApiBase(config, model) {
|
|
|
5768
6107
|
}
|
|
5769
6108
|
return null;
|
|
5770
6109
|
}
|
|
6110
|
+
function buildConfigSchema(options) {
|
|
6111
|
+
const schema = zodToJsonSchema(ConfigSchema, {
|
|
6112
|
+
name: "NextClawConfig",
|
|
6113
|
+
target: "jsonSchema7"
|
|
6114
|
+
});
|
|
6115
|
+
if (schema && typeof schema === "object") {
|
|
6116
|
+
schema.title = "NextClawConfig";
|
|
6117
|
+
}
|
|
6118
|
+
const hints = mapSensitivePaths(ConfigSchema, "", buildBaseHints());
|
|
6119
|
+
return {
|
|
6120
|
+
schema,
|
|
6121
|
+
uiHints: hints,
|
|
6122
|
+
version: options?.version ?? getPackageVersion(),
|
|
6123
|
+
generatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
6124
|
+
};
|
|
6125
|
+
}
|
|
5771
6126
|
|
|
5772
6127
|
// src/config/loader.ts
|
|
5773
6128
|
function getConfigPath() {
|
|
@@ -5780,12 +6135,12 @@ function loadConfig(configPath) {
|
|
|
5780
6135
|
const path = configPath ?? getConfigPath();
|
|
5781
6136
|
if (existsSync10(path)) {
|
|
5782
6137
|
try {
|
|
5783
|
-
const raw =
|
|
6138
|
+
const raw = readFileSync9(path, "utf-8");
|
|
5784
6139
|
const data = JSON.parse(raw);
|
|
5785
6140
|
const migrated = migrateConfig(data);
|
|
5786
6141
|
return ConfigSchema.parse(migrated);
|
|
5787
6142
|
} catch (err) {
|
|
5788
|
-
const message = err instanceof
|
|
6143
|
+
const message = err instanceof z3.ZodError ? err.message : String(err);
|
|
5789
6144
|
console.warn(`Warning: Failed to load config from ${path}: ${message}`);
|
|
5790
6145
|
}
|
|
5791
6146
|
}
|
|
@@ -5894,8 +6249,66 @@ function buildReloadPlan(changedPaths) {
|
|
|
5894
6249
|
return plan;
|
|
5895
6250
|
}
|
|
5896
6251
|
|
|
6252
|
+
// src/config/redact.ts
|
|
6253
|
+
function matchHint(path, hints) {
|
|
6254
|
+
const direct = hints[path];
|
|
6255
|
+
if (direct) {
|
|
6256
|
+
return direct;
|
|
6257
|
+
}
|
|
6258
|
+
const segments = path.split(".");
|
|
6259
|
+
for (const [hintKey, hint] of Object.entries(hints)) {
|
|
6260
|
+
if (!hintKey.includes("*")) {
|
|
6261
|
+
continue;
|
|
6262
|
+
}
|
|
6263
|
+
const hintSegments = hintKey.split(".");
|
|
6264
|
+
if (hintSegments.length !== segments.length) {
|
|
6265
|
+
continue;
|
|
6266
|
+
}
|
|
6267
|
+
let match = true;
|
|
6268
|
+
for (let i = 0; i < segments.length; i += 1) {
|
|
6269
|
+
if (hintSegments[i] !== "*" && hintSegments[i] !== segments[i]) {
|
|
6270
|
+
match = false;
|
|
6271
|
+
break;
|
|
6272
|
+
}
|
|
6273
|
+
}
|
|
6274
|
+
if (match) {
|
|
6275
|
+
return hint;
|
|
6276
|
+
}
|
|
6277
|
+
}
|
|
6278
|
+
return void 0;
|
|
6279
|
+
}
|
|
6280
|
+
function isSensitivePath(path, hints) {
|
|
6281
|
+
if (hints) {
|
|
6282
|
+
const hint = matchHint(path, hints);
|
|
6283
|
+
if (hint?.sensitive !== void 0) {
|
|
6284
|
+
return Boolean(hint.sensitive);
|
|
6285
|
+
}
|
|
6286
|
+
}
|
|
6287
|
+
return isSensitiveConfigPath(path);
|
|
6288
|
+
}
|
|
6289
|
+
function redactConfigObject(value, hints, prefix = "") {
|
|
6290
|
+
if (Array.isArray(value)) {
|
|
6291
|
+
const nextPath = prefix ? `${prefix}[]` : "[]";
|
|
6292
|
+
return value.map((entry) => redactConfigObject(entry, hints, nextPath));
|
|
6293
|
+
}
|
|
6294
|
+
if (!value || typeof value !== "object") {
|
|
6295
|
+
return value;
|
|
6296
|
+
}
|
|
6297
|
+
const entries = value;
|
|
6298
|
+
const output = {};
|
|
6299
|
+
for (const [key, val] of Object.entries(entries)) {
|
|
6300
|
+
const nextPath = prefix ? `${prefix}.${key}` : key;
|
|
6301
|
+
if (isSensitivePath(nextPath, hints)) {
|
|
6302
|
+
output[key] = val ? "***" : val;
|
|
6303
|
+
continue;
|
|
6304
|
+
}
|
|
6305
|
+
output[key] = redactConfigObject(val, hints, nextPath);
|
|
6306
|
+
}
|
|
6307
|
+
return output;
|
|
6308
|
+
}
|
|
6309
|
+
|
|
5897
6310
|
// src/cron/service.ts
|
|
5898
|
-
import { readFileSync as
|
|
6311
|
+
import { readFileSync as readFileSync10, writeFileSync as writeFileSync7, existsSync as existsSync11, mkdirSync as mkdirSync6 } from "fs";
|
|
5899
6312
|
import { dirname as dirname2 } from "path";
|
|
5900
6313
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
5901
6314
|
import cronParser from "cron-parser";
|
|
@@ -5935,7 +6348,7 @@ var CronService = class {
|
|
|
5935
6348
|
}
|
|
5936
6349
|
if (existsSync11(this.storePath)) {
|
|
5937
6350
|
try {
|
|
5938
|
-
const data = JSON.parse(
|
|
6351
|
+
const data = JSON.parse(readFileSync10(this.storePath, "utf-8"));
|
|
5939
6352
|
const jobs = (data.jobs ?? []).map((job) => ({
|
|
5940
6353
|
id: String(job.id),
|
|
5941
6354
|
name: String(job.name),
|
|
@@ -6138,7 +6551,7 @@ var CronService = class {
|
|
|
6138
6551
|
};
|
|
6139
6552
|
|
|
6140
6553
|
// src/heartbeat/service.ts
|
|
6141
|
-
import { readFileSync as
|
|
6554
|
+
import { readFileSync as readFileSync11, existsSync as existsSync12 } from "fs";
|
|
6142
6555
|
import { join as join9 } from "path";
|
|
6143
6556
|
var DEFAULT_HEARTBEAT_INTERVAL_S = 30 * 60;
|
|
6144
6557
|
var HEARTBEAT_PROMPT = "Read HEARTBEAT.md in your workspace (if it exists).\nFollow any instructions or tasks listed there.\nIf nothing needs attention, reply with just: HEARTBEAT_OK";
|
|
@@ -6172,7 +6585,7 @@ var HeartbeatService = class {
|
|
|
6172
6585
|
readHeartbeatFile() {
|
|
6173
6586
|
if (existsSync12(this.heartbeatFile)) {
|
|
6174
6587
|
try {
|
|
6175
|
-
return
|
|
6588
|
+
return readFileSync11(this.heartbeatFile, "utf-8");
|
|
6176
6589
|
} catch {
|
|
6177
6590
|
return null;
|
|
6178
6591
|
}
|
|
@@ -6615,6 +7028,9 @@ export {
|
|
|
6615
7028
|
WebSearchConfigSchema,
|
|
6616
7029
|
WebToolsConfigSchema,
|
|
6617
7030
|
WhatsAppConfigSchema,
|
|
7031
|
+
applySensitiveHints,
|
|
7032
|
+
buildBaseHints,
|
|
7033
|
+
buildConfigSchema,
|
|
6618
7034
|
buildReloadPlan,
|
|
6619
7035
|
diffConfigPaths,
|
|
6620
7036
|
ensureDir,
|
|
@@ -6628,17 +7044,21 @@ export {
|
|
|
6628
7044
|
getDataDir,
|
|
6629
7045
|
getDataPath,
|
|
6630
7046
|
getMemoryPath,
|
|
7047
|
+
getPackageVersion,
|
|
6631
7048
|
getProvider,
|
|
6632
7049
|
getProviderName,
|
|
6633
7050
|
getSessionsPath,
|
|
6634
7051
|
getSkillsPath,
|
|
6635
7052
|
getWorkspacePath,
|
|
6636
7053
|
getWorkspacePathFromConfig,
|
|
7054
|
+
isSensitiveConfigPath,
|
|
6637
7055
|
loadConfig,
|
|
7056
|
+
mapSensitivePaths,
|
|
6638
7057
|
matchProvider,
|
|
6639
7058
|
parseSessionKey,
|
|
6640
7059
|
probeFeishu,
|
|
6641
7060
|
providerLabel,
|
|
7061
|
+
redactConfigObject,
|
|
6642
7062
|
safeFilename,
|
|
6643
7063
|
saveConfig,
|
|
6644
7064
|
timestamp,
|