clawdbot 2026.1.4 → 2026.1.5-1
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/CHANGELOG.md +32 -1
- package/README.md +26 -1
- package/dist/agents/pi-embedded-runner.js +2 -0
- package/dist/agents/pi-embedded-subscribe.js +18 -3
- package/dist/agents/pi-tools.js +45 -6
- package/dist/agents/tools/browser-tool.js +38 -89
- package/dist/agents/tools/cron-tool.js +8 -8
- package/dist/agents/workspace.js +8 -1
- package/dist/auto-reply/command-detection.js +26 -0
- package/dist/auto-reply/reply/agent-runner.js +15 -8
- package/dist/auto-reply/reply/commands.js +36 -25
- package/dist/auto-reply/reply/directive-handling.js +4 -2
- package/dist/auto-reply/reply/directives.js +12 -0
- package/dist/auto-reply/reply/session-updates.js +2 -4
- package/dist/auto-reply/reply.js +26 -4
- package/dist/browser/config.js +22 -4
- package/dist/browser/profiles-service.js +3 -1
- package/dist/browser/profiles.js +14 -3
- package/dist/canvas-host/a2ui/.bundle.hash +2 -0
- package/dist/cli/gateway-cli.js +2 -2
- package/dist/cli/profile.js +81 -0
- package/dist/cli/program.js +10 -1
- package/dist/cli/run-main.js +33 -0
- package/dist/commands/configure.js +5 -0
- package/dist/commands/onboard-providers.js +1 -1
- package/dist/commands/setup.js +4 -1
- package/dist/config/defaults.js +56 -0
- package/dist/config/io.js +47 -6
- package/dist/config/paths.js +2 -2
- package/dist/config/port-defaults.js +32 -0
- package/dist/config/sessions.js +3 -2
- package/dist/config/validation.js +2 -2
- package/dist/config/zod-schema.js +16 -0
- package/dist/discord/monitor.js +75 -266
- package/dist/entry.js +16 -0
- package/dist/gateway/call.js +8 -1
- package/dist/gateway/server-methods/chat.js +1 -1
- package/dist/gateway/server.js +14 -3
- package/dist/index.js +2 -2
- package/dist/infra/control-ui-assets.js +118 -0
- package/dist/infra/dotenv.js +15 -0
- package/dist/infra/shell-env.js +79 -0
- package/dist/infra/system-events.js +50 -23
- package/dist/macos/relay.js +8 -2
- package/dist/sessions/send-policy.js +68 -0
- package/dist/telegram/bot.js +24 -1
- package/dist/utils.js +8 -2
- package/dist/web/auto-reply.js +18 -21
- package/dist/web/inbound.js +5 -1
- package/dist/web/qr-image.js +4 -4
- package/dist/web/session.js +2 -3
- package/docs/agent.md +0 -2
- package/docs/assets/markdown.css +4 -1
- package/docs/audio.md +0 -2
- package/docs/clawd.md +0 -2
- package/docs/configuration.md +62 -3
- package/docs/docs.json +9 -1
- package/docs/faq.md +32 -7
- package/docs/gateway.md +28 -0
- package/docs/images.md +0 -2
- package/docs/index.md +2 -4
- package/docs/mac/icon.md +1 -1
- package/docs/nix.md +57 -11
- package/docs/onboarding.md +0 -2
- package/docs/refactor/webagent-session.md +0 -2
- package/docs/research/memory.md +1 -1
- package/docs/skills.md +0 -2
- package/docs/templates/AGENTS.md +2 -2
- package/docs/tools.md +15 -0
- package/docs/whatsapp.md +2 -0
- package/package.json +9 -8
package/dist/config/defaults.js
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
import { resolveTalkApiKey } from "./talk.js";
|
|
2
2
|
let defaultWarnState = { warned: false };
|
|
3
|
+
const DEFAULT_MODEL_ALIASES = {
|
|
4
|
+
// Anthropic (pi-ai catalog uses "latest" ids without date suffix)
|
|
5
|
+
opus: "anthropic/claude-opus-4-5",
|
|
6
|
+
sonnet: "anthropic/claude-sonnet-4-5",
|
|
7
|
+
// OpenAI
|
|
8
|
+
gpt: "openai/gpt-5.2",
|
|
9
|
+
"gpt-mini": "openai/gpt-5-mini",
|
|
10
|
+
// Google Gemini (3.x are preview ids in the catalog)
|
|
11
|
+
gemini: "google/gemini-3-pro-preview",
|
|
12
|
+
"gemini-flash": "google/gemini-3-flash-preview",
|
|
13
|
+
};
|
|
3
14
|
function escapeRegExp(text) {
|
|
4
15
|
return text.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
5
16
|
}
|
|
@@ -56,6 +67,51 @@ export function applyTalkApiKey(config) {
|
|
|
56
67
|
},
|
|
57
68
|
};
|
|
58
69
|
}
|
|
70
|
+
function normalizeAliasKey(value) {
|
|
71
|
+
return value.trim().toLowerCase();
|
|
72
|
+
}
|
|
73
|
+
export function applyModelAliasDefaults(cfg) {
|
|
74
|
+
const existingAgent = cfg.agent;
|
|
75
|
+
if (!existingAgent)
|
|
76
|
+
return cfg;
|
|
77
|
+
const existingAliases = existingAgent?.modelAliases ?? {};
|
|
78
|
+
const byNormalized = new Map();
|
|
79
|
+
for (const key of Object.keys(existingAliases)) {
|
|
80
|
+
const norm = normalizeAliasKey(key);
|
|
81
|
+
if (!norm)
|
|
82
|
+
continue;
|
|
83
|
+
if (!byNormalized.has(norm))
|
|
84
|
+
byNormalized.set(norm, key);
|
|
85
|
+
}
|
|
86
|
+
let mutated = false;
|
|
87
|
+
const nextAliases = { ...existingAliases };
|
|
88
|
+
for (const [canonicalKey, target] of Object.entries(DEFAULT_MODEL_ALIASES)) {
|
|
89
|
+
const norm = normalizeAliasKey(canonicalKey);
|
|
90
|
+
const existingKey = byNormalized.get(norm);
|
|
91
|
+
if (!existingKey) {
|
|
92
|
+
nextAliases[canonicalKey] = target;
|
|
93
|
+
byNormalized.set(norm, canonicalKey);
|
|
94
|
+
mutated = true;
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
const existingValue = String(existingAliases[existingKey] ?? "");
|
|
98
|
+
if (existingKey !== canonicalKey && existingValue === target) {
|
|
99
|
+
delete nextAliases[existingKey];
|
|
100
|
+
nextAliases[canonicalKey] = target;
|
|
101
|
+
byNormalized.set(norm, canonicalKey);
|
|
102
|
+
mutated = true;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
if (!mutated)
|
|
106
|
+
return cfg;
|
|
107
|
+
return {
|
|
108
|
+
...cfg,
|
|
109
|
+
agent: {
|
|
110
|
+
...existingAgent,
|
|
111
|
+
modelAliases: nextAliases,
|
|
112
|
+
},
|
|
113
|
+
};
|
|
114
|
+
}
|
|
59
115
|
export function resetSessionDefaultsWarningForTests() {
|
|
60
116
|
defaultWarnState = { warned: false };
|
|
61
117
|
}
|
package/dist/config/io.js
CHANGED
|
@@ -2,11 +2,27 @@ import fs from "node:fs";
|
|
|
2
2
|
import os from "node:os";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import JSON5 from "json5";
|
|
5
|
-
import {
|
|
5
|
+
import { loadShellEnvFallback, resolveShellEnvFallbackTimeoutMs, shouldEnableShellEnvFallback, } from "../infra/shell-env.js";
|
|
6
|
+
import { applyIdentityDefaults, applyModelAliasDefaults, applySessionDefaults, applyTalkApiKey, } from "./defaults.js";
|
|
6
7
|
import { findLegacyConfigIssues } from "./legacy.js";
|
|
7
8
|
import { CONFIG_PATH_CLAWDBOT, resolveConfigPath, resolveStateDir, } from "./paths.js";
|
|
8
9
|
import { validateConfigObject } from "./validation.js";
|
|
9
10
|
import { ClawdbotSchema } from "./zod-schema.js";
|
|
11
|
+
const SHELL_ENV_EXPECTED_KEYS = [
|
|
12
|
+
"OPENAI_API_KEY",
|
|
13
|
+
"ANTHROPIC_API_KEY",
|
|
14
|
+
"ANTHROPIC_OAUTH_TOKEN",
|
|
15
|
+
"GEMINI_API_KEY",
|
|
16
|
+
"ZAI_API_KEY",
|
|
17
|
+
"MINIMAX_API_KEY",
|
|
18
|
+
"ELEVENLABS_API_KEY",
|
|
19
|
+
"TELEGRAM_BOT_TOKEN",
|
|
20
|
+
"DISCORD_BOT_TOKEN",
|
|
21
|
+
"SLACK_BOT_TOKEN",
|
|
22
|
+
"SLACK_APP_TOKEN",
|
|
23
|
+
"CLAWDBOT_GATEWAY_TOKEN",
|
|
24
|
+
"CLAWDBOT_GATEWAY_PASSWORD",
|
|
25
|
+
];
|
|
10
26
|
function resolveConfigPathForDeps(deps) {
|
|
11
27
|
if (deps.configPath)
|
|
12
28
|
return deps.configPath;
|
|
@@ -35,8 +51,18 @@ export function createConfigIO(overrides = {}) {
|
|
|
35
51
|
const configPath = resolveConfigPathForDeps(deps);
|
|
36
52
|
function loadConfig() {
|
|
37
53
|
try {
|
|
38
|
-
if (!deps.fs.existsSync(configPath))
|
|
54
|
+
if (!deps.fs.existsSync(configPath)) {
|
|
55
|
+
if (shouldEnableShellEnvFallback(deps.env)) {
|
|
56
|
+
loadShellEnvFallback({
|
|
57
|
+
enabled: true,
|
|
58
|
+
env: deps.env,
|
|
59
|
+
expectedKeys: SHELL_ENV_EXPECTED_KEYS,
|
|
60
|
+
logger: deps.logger,
|
|
61
|
+
timeoutMs: resolveShellEnvFallbackTimeoutMs(deps.env),
|
|
62
|
+
});
|
|
63
|
+
}
|
|
39
64
|
return {};
|
|
65
|
+
}
|
|
40
66
|
const raw = deps.fs.readFileSync(configPath, "utf-8");
|
|
41
67
|
const parsed = deps.json5.parse(raw);
|
|
42
68
|
if (typeof parsed !== "object" || parsed === null)
|
|
@@ -49,7 +75,20 @@ export function createConfigIO(overrides = {}) {
|
|
|
49
75
|
}
|
|
50
76
|
return {};
|
|
51
77
|
}
|
|
52
|
-
|
|
78
|
+
const cfg = applyModelAliasDefaults(applySessionDefaults(applyIdentityDefaults(validated.data)));
|
|
79
|
+
const enabled = shouldEnableShellEnvFallback(deps.env) ||
|
|
80
|
+
cfg.env?.shellEnv?.enabled === true;
|
|
81
|
+
if (enabled) {
|
|
82
|
+
loadShellEnvFallback({
|
|
83
|
+
enabled: true,
|
|
84
|
+
env: deps.env,
|
|
85
|
+
expectedKeys: SHELL_ENV_EXPECTED_KEYS,
|
|
86
|
+
logger: deps.logger,
|
|
87
|
+
timeoutMs: cfg.env?.shellEnv?.timeoutMs ??
|
|
88
|
+
resolveShellEnvFallbackTimeoutMs(deps.env),
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
return cfg;
|
|
53
92
|
}
|
|
54
93
|
catch (err) {
|
|
55
94
|
deps.logger.error(`Failed to read config at ${configPath}`, err);
|
|
@@ -59,7 +98,7 @@ export function createConfigIO(overrides = {}) {
|
|
|
59
98
|
async function readConfigFileSnapshot() {
|
|
60
99
|
const exists = deps.fs.existsSync(configPath);
|
|
61
100
|
if (!exists) {
|
|
62
|
-
const config = applyTalkApiKey(applySessionDefaults({}));
|
|
101
|
+
const config = applyTalkApiKey(applyModelAliasDefaults(applySessionDefaults({})));
|
|
63
102
|
const legacyIssues = [];
|
|
64
103
|
return {
|
|
65
104
|
path: configPath,
|
|
@@ -109,7 +148,7 @@ export function createConfigIO(overrides = {}) {
|
|
|
109
148
|
raw,
|
|
110
149
|
parsed: parsedRes.parsed,
|
|
111
150
|
valid: true,
|
|
112
|
-
config: applyTalkApiKey(applySessionDefaults(validated.config)),
|
|
151
|
+
config: applyTalkApiKey(applyModelAliasDefaults(applySessionDefaults(validated.config))),
|
|
113
152
|
issues: [],
|
|
114
153
|
legacyIssues,
|
|
115
154
|
};
|
|
@@ -131,7 +170,9 @@ export function createConfigIO(overrides = {}) {
|
|
|
131
170
|
await deps.fs.promises.mkdir(path.dirname(configPath), {
|
|
132
171
|
recursive: true,
|
|
133
172
|
});
|
|
134
|
-
const json = JSON.stringify(cfg, null, 2)
|
|
173
|
+
const json = JSON.stringify(applyModelAliasDefaults(cfg), null, 2)
|
|
174
|
+
.trimEnd()
|
|
175
|
+
.concat("\n");
|
|
135
176
|
await deps.fs.promises.writeFile(configPath, json, "utf-8");
|
|
136
177
|
}
|
|
137
178
|
return {
|
package/dist/config/paths.js
CHANGED
|
@@ -18,9 +18,9 @@ export const isNixMode = resolveIsNixMode();
|
|
|
18
18
|
* Default: ~/.clawdbot
|
|
19
19
|
*/
|
|
20
20
|
export function resolveStateDir(env = process.env, homedir = os.homedir) {
|
|
21
|
-
const override = env.CLAWDBOT_STATE_DIR?.trim();
|
|
21
|
+
const override = env.CLAWDBOT_STATE_DIR?.trim() || env.CLAWDIS_STATE_DIR?.trim();
|
|
22
22
|
if (override)
|
|
23
|
-
return override;
|
|
23
|
+
return resolveUserPath(override);
|
|
24
24
|
return path.join(homedir(), ".clawdbot");
|
|
25
25
|
}
|
|
26
26
|
export const STATE_DIR_CLAWDBOT = resolveStateDir();
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
function isValidPort(port) {
|
|
2
|
+
return Number.isFinite(port) && port > 0 && port <= 65535;
|
|
3
|
+
}
|
|
4
|
+
function clampPort(port, fallback) {
|
|
5
|
+
return isValidPort(port) ? port : fallback;
|
|
6
|
+
}
|
|
7
|
+
function derivePort(base, offset, fallback) {
|
|
8
|
+
return clampPort(base + offset, fallback);
|
|
9
|
+
}
|
|
10
|
+
export const DEFAULT_BRIDGE_PORT = 18790;
|
|
11
|
+
export const DEFAULT_BROWSER_CONTROL_PORT = 18791;
|
|
12
|
+
export const DEFAULT_CANVAS_HOST_PORT = 18793;
|
|
13
|
+
export const DEFAULT_BROWSER_CDP_PORT_RANGE_START = 18800;
|
|
14
|
+
export const DEFAULT_BROWSER_CDP_PORT_RANGE_END = 18899;
|
|
15
|
+
export function deriveDefaultBridgePort(gatewayPort) {
|
|
16
|
+
return derivePort(gatewayPort, 1, DEFAULT_BRIDGE_PORT);
|
|
17
|
+
}
|
|
18
|
+
export function deriveDefaultBrowserControlPort(gatewayPort) {
|
|
19
|
+
return derivePort(gatewayPort, 2, DEFAULT_BROWSER_CONTROL_PORT);
|
|
20
|
+
}
|
|
21
|
+
export function deriveDefaultCanvasHostPort(gatewayPort) {
|
|
22
|
+
return derivePort(gatewayPort, 4, DEFAULT_CANVAS_HOST_PORT);
|
|
23
|
+
}
|
|
24
|
+
export function deriveDefaultBrowserCdpPortRange(browserControlPort) {
|
|
25
|
+
const start = derivePort(browserControlPort, 9, DEFAULT_BROWSER_CDP_PORT_RANGE_START);
|
|
26
|
+
const end = clampPort(start +
|
|
27
|
+
(DEFAULT_BROWSER_CDP_PORT_RANGE_END -
|
|
28
|
+
DEFAULT_BROWSER_CDP_PORT_RANGE_START), DEFAULT_BROWSER_CDP_PORT_RANGE_END);
|
|
29
|
+
if (end < start)
|
|
30
|
+
return { start, end: start };
|
|
31
|
+
return { start, end };
|
|
32
|
+
}
|
package/dist/config/sessions.js
CHANGED
|
@@ -4,6 +4,7 @@ import os from "node:os";
|
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
import JSON5 from "json5";
|
|
6
6
|
import { normalizeE164 } from "../utils.js";
|
|
7
|
+
import { resolveStateDir } from "./paths.js";
|
|
7
8
|
const GROUP_SURFACES = new Set([
|
|
8
9
|
"whatsapp",
|
|
9
10
|
"telegram",
|
|
@@ -13,8 +14,8 @@ const GROUP_SURFACES = new Set([
|
|
|
13
14
|
"webchat",
|
|
14
15
|
"slack",
|
|
15
16
|
]);
|
|
16
|
-
export function resolveSessionTranscriptsDir() {
|
|
17
|
-
return path.join(
|
|
17
|
+
export function resolveSessionTranscriptsDir(env = process.env, homedir = os.homedir) {
|
|
18
|
+
return path.join(resolveStateDir(env, homedir), "sessions");
|
|
18
19
|
}
|
|
19
20
|
export function resolveDefaultSessionStorePath() {
|
|
20
21
|
return path.join(resolveSessionTranscriptsDir(), "sessions.json");
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { applyIdentityDefaults, applySessionDefaults } from "./defaults.js";
|
|
1
|
+
import { applyIdentityDefaults, applyModelAliasDefaults, applySessionDefaults, } from "./defaults.js";
|
|
2
2
|
import { findLegacyConfigIssues } from "./legacy.js";
|
|
3
3
|
import { ClawdbotSchema } from "./zod-schema.js";
|
|
4
4
|
export function validateConfigObject(raw) {
|
|
@@ -24,6 +24,6 @@ export function validateConfigObject(raw) {
|
|
|
24
24
|
}
|
|
25
25
|
return {
|
|
26
26
|
ok: true,
|
|
27
|
-
config: applySessionDefaults(applyIdentityDefaults(validated.data)),
|
|
27
|
+
config: applyModelAliasDefaults(applySessionDefaults(applyIdentityDefaults(validated.data))),
|
|
28
28
|
};
|
|
29
29
|
}
|
|
@@ -256,6 +256,16 @@ const HooksGmailSchema = z
|
|
|
256
256
|
})
|
|
257
257
|
.optional();
|
|
258
258
|
export const ClawdbotSchema = z.object({
|
|
259
|
+
env: z
|
|
260
|
+
.object({
|
|
261
|
+
shellEnv: z
|
|
262
|
+
.object({
|
|
263
|
+
enabled: z.boolean().optional(),
|
|
264
|
+
timeoutMs: z.number().int().nonnegative().optional(),
|
|
265
|
+
})
|
|
266
|
+
.optional(),
|
|
267
|
+
})
|
|
268
|
+
.optional(),
|
|
259
269
|
identity: z
|
|
260
270
|
.object({
|
|
261
271
|
name: z.string().optional(),
|
|
@@ -346,6 +356,12 @@ export const ClawdbotSchema = z.object({
|
|
|
346
356
|
modelFallbacks: z.array(z.string()).optional(),
|
|
347
357
|
imageModelFallbacks: z.array(z.string()).optional(),
|
|
348
358
|
contextTokens: z.number().int().positive().optional(),
|
|
359
|
+
tools: z
|
|
360
|
+
.object({
|
|
361
|
+
allow: z.array(z.string()).optional(),
|
|
362
|
+
deny: z.array(z.string()).optional(),
|
|
363
|
+
})
|
|
364
|
+
.optional(),
|
|
349
365
|
thinkingDefault: z
|
|
350
366
|
.union([
|
|
351
367
|
z.literal("off"),
|